C++链表单元测试returns段错误
C++ Linked list unit test returns segment fault
我实现链表的算法如下
- 添加新节点和returns位置指针的函数。
- 处理添加节点前端、端操作的核心函数。
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);
}
当我运行这段代码时,测试通过但我得到
Segmentation fault
我错过了什么?
newNode
in addNewNode
从未被初始化,所以它是指向任何地方的指针:
LinkedList* addNewNode(int nodeVal) {
LinkedList *newNode; // Uninitialized, so undefined
newNode->value = nodeVal; // `->` dereferences the pointer, but it goes nowhere!
初始化它的一种方法是使用堆分配,即运算符 new
- 但请记住,您需要在 C++ 中管理资源,因此您需要 free 使用完毕后。
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 并从那里开始删除。如果在删除其后继节点之前删除了一个节点,则会造成内存泄漏 bc。您不再有释放该内存的指针。
还要确保打开编译器警告!默认设置 way 太宽松了。例如,对于 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
我实现链表的算法如下
- 添加新节点和returns位置指针的函数。
- 处理添加节点前端、端操作的核心函数。
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);
}
当我运行这段代码时,测试通过但我得到
Segmentation fault
我错过了什么?
newNode
in addNewNode
从未被初始化,所以它是指向任何地方的指针:
LinkedList* addNewNode(int nodeVal) {
LinkedList *newNode; // Uninitialized, so undefined
newNode->value = nodeVal; // `->` dereferences the pointer, but it goes nowhere!
初始化它的一种方法是使用堆分配,即运算符 new
- 但请记住,您需要在 C++ 中管理资源,因此您需要 free 使用完毕后。
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 并从那里开始删除。如果在删除其后继节点之前删除了一个节点,则会造成内存泄漏 bc。您不再有释放该内存的指针。
还要确保打开编译器警告!默认设置 way 太宽松了。例如,对于 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