我实现链表的算法如下
- 添加新节点并返回位置指针。
- 一个核心功能,处理添加节点的前端、末端操作。
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