c++链表单元测试返回段错误



我实现链表的算法如下

  • 添加新节点并返回位置指针。
  • 一个核心功能,处理添加节点的前端、末端操作。

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从未初始化,因此它是一个指向任何地方的指针:

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,你首先必须走到它的结尾并从那里开始删除。如果在删除后继节点之前删除一个节点,则会创建内存泄漏bc。你不再有一个指针来释放内存。

还要确保打开编译器警告!默认设置方式太宽松了。例如,对于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

最新更新