【问题标题】:C++ Linked list unit test returns segment fault [closed]C ++链表单元测试返回段错误[关闭]
【发布时间】:2021-11-24 03:00:55
【问题描述】:

我实现链表的算法如下

  • 添加新节点并返回位置指针的函数。
  • 处理添加节点前端、后端操作的核心函数。

linkedList.hpp

#include <cstddef>

class LinkedList{
  public:
    int value {0};
    LinkedList* nextNode {NULL};
};

LinkedList* addNewNode(int nodeVal){

  LinkedList *newNode;
  newNode->value = nodeVal;
  newNode->nextNode = nullptr;

  return newNode;
}

googletest下面的单元测试检查是否

  • 返回的节点指针不为空。
  • 返回的节点有值。
  • 返回节点的下一个节点值设置为 NULL。

linkedListTest.cpp

#include <gtest/gtest.h>
#include "../linkedList.hpp"

int main(int argc, char **argv){
    ::testing::InitGoogleTest(&argc,argv);
    return RUN_ALL_TESTS();

}

class LinkedListTest : public ::testing::Test{

    public:
        LinkedList *linkedlist = new LinkedList();
        virtual void SetUp(){
            }
        virtual void TearDown(){
            delete linkedlist;
        }
};
TEST_F(LinkedListTest,addNewNodeReturnsItsNodePointer){

    // act
    linkedlist = addNewNode(5);

    EXPECT_TRUE(linkedlist != nullptr);
    ASSERT_EQ(linkedlist->value,5);
    EXPECT_TRUE(linkedlist->nextNode != nullptr);

}

当我运行此代码时,测试通过但我得到了

分段错误

我错过了什么?

【问题讨论】:

  • 你的编译器应该警告你addNewNode中的问题,如果它没有把警告变成最大。
  • newNode in addNewNode 未初始化。这是一个指向无处的指针。你用的是什么编译器?您应该启用更多警告,例如,对于 GCC -Wall。此外,当您有段错误时,使用调试信息进行编译并在调试器中运行您的可执行文件。它可以为您提供段错误原因的堆栈跟踪(大多数情况下)。
  • @BenjaminMaurer 是的,这就是问题所在。您能否将其发布为答案,以便我接受。

标签: c++ unit-testing linked-list googletest


【解决方案1】:

addNewNode 中的newNode 从未初始化,因此它是一个指向无处的指针:

LinkedList* addNewNode(int nodeVal) {
  LinkedList *newNode;  // Uninitialized, so undefined
  newNode->value = nodeVal;  // `->` dereferences the pointer, but it goes nowhere!

初始化它的一种方法是使用堆分配,即运算符new - 但请记住,您需要在 C++ 中管理资源,因此您需要在完成使用后释放它它。

  LinkedList* addNewNode(int nodeVal) {
      LinkedList *newNode = new LinkedList();
      newNode->value = nodeVal;
      newNode->nextNode = nullptr;

稍后,要释放内存,您可以执行以下操作:

if (myNode->nextNode != nullptr) {
    delete myNode->nextNode;
    myNode.nextNode = nullptr;
}

但是如果你想删除整个LinkedList,你首先必须走到它的end,然后从那里开始删除。如果在删除后继节点之前删除节点,则会造成内存泄漏。您不再有释放该内存的指针。

还要确保打开编译器警告!默认设置方式过于宽松。例如,对于 GCC,您可以使用 -Wall。这告诉我:

<source>: In function 'LinkedList* addNewNode(int)':
<source>:12:18: warning: 'newNode' is used uninitialized [-Wuninitialized]
   12 |   newNode->value = nodeVal;
      |   ~~~~~~~~~~~~~~~^~~~~~~~~

当你遇到分段错误(segfault)时,你应该在调试模式下编译你的程序并在调试器中运行它。它可以告诉你错误发生在哪里:

gcc -g -Og -o myprog myprog.c
gdb ./myprog
run
(segfault)
backtrace

【讨论】:

    猜你喜欢
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 2014-11-08
    • 1970-01-01
    • 2011-01-03
    • 2023-02-07
    • 2013-11-24
    • 2010-09-09
    相关资源
    最近更新 更多