- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
对于我正在上的一门课,我们正在用 C++ 实现我们自己的单向链表,以便我们可以更好地理解数据结构的功能。目前,我已经完成了代码,它通过了所有测试用例,但是运行 valgrind 我发现我仍然有内存泄漏。
我已经实现了应该删除每个节点对象的代码,只要它从列表中删除,但显然我做错了什么。 关于我缺少的内存管理,我不了解什么?
我的代码通过了一些基本测试,没有内存泄漏,但是当使用我的教授提供的更严格的测试用例时,valgrind 出现了严重的内存泄漏问题。
这是我的链表类:
template<typename T>
class LinkedList: public LinkedListInterface<T> {
private:
struct Node {
Node(T val) {
value = val;
next = NULL;
}
T value;
Node *next;
};
Node *head;
public:
LinkedList() {
head = NULL;
}
~LinkedList() {
}
void insertHead(T value) {
cout << "In insertHead function" << endl;
Node *newNode = new Node(value);
if(head == NULL){
head = newNode;
}
else {
newNode->next = head;
head = newNode;
}
}
//don't allow duplicate values in the list. Implement later.
void insertTail(T value) {
cout << "In insertTail function" << endl;
Node *newNode = new Node(value);
if(head == NULL) {
head = newNode;
}
else {
//find last node
Node *fakeIterator = head;
//while what fake iterator is pointing to is not NULL then make it point to the next pointer.
while (fakeIterator->next != NULL) {
fakeIterator = fakeIterator->next;
}
//set that node's next pointer to newNode
fakeIterator->next = newNode;
}
}
void insertAfter(T value, T insertionNode) {
cout << "In insertAfter function" << endl;
Node *fakeIterator = head;
while(fakeIterator != NULL) {
if (fakeIterator->value == insertionNode) {
Node *newNode = new Node(value);
newNode->next = fakeIterator->next;
fakeIterator->next = newNode;
break;
}
fakeIterator = fakeIterator->next;
}
}
string toString() {
cout << "In toString function" << endl;
stringstream ss;
Node *fakeIterator = head;
while (fakeIterator != NULL) {
if (fakeIterator->next == NULL)
ss << fakeIterator->value;
else
ss << fakeIterator->value << ", ";
fakeIterator = fakeIterator->next;
}
return ss.str();
}
void remove(T value) {
cout << "In remove function" << endl;
if (head != NULL) {
Node *fakeIterator = head;
if(head->value == value) {
Node *nodeToDelete = head;//new Node(value);
// nodeToDelete = head;
head = head->next;
delete nodeToDelete;
}
else {
while(fakeIterator->next != NULL) {
//if the value of the node after this one equals the value
if ( (fakeIterator->next)->value == value) {
//make a temp node to store the node being destroyed
Node *nodeToDelete = fakeIterator->next;
//change "next" to point to the item after the one being deleted
fakeIterator->next = fakeIterator->next->next;
//delete the node
delete nodeToDelete;
break;
}
fakeIterator = fakeIterator->next;
}
}
}
}
void clear() {
cout << "In clear function" << endl;
while (head != NULL) {
remove(head->value);
}
}
T at(int index) {
cout << "In at function" << endl;
Node *fakeIterator = head;
if (head == NULL) {
throw out_of_range("list is empty");
}
for (int i = 0; i < index ; i++) {
cout << "2" << endl;
if (fakeIterator->next == NULL) {
cout << "3" << endl;
throw out_of_range("index does not exist");
break;
}
fakeIterator = fakeIterator->next;
cout << "4" << endl;
}
return fakeIterator->value;
}
int size() {
cout << "In size function" << endl;
int sizeOfList = 0;
Node *fakeIterator = head;
while (fakeIterator != NULL) {
if (fakeIterator->next == NULL)
return sizeOfList;
else
sizeOfList++;
fakeIterator = fakeIterator->next;
}
}
};
这是 valgrind 的输出:
==14052== Process terminating with default action of signal 2 (SIGINT)
==14052== at 0x57BFFE0: __read_nocancel (in /lib64/libc-2.17.so)
==14052== by 0x574CB83: _IO_file_underflow@@GLIBC_2.2.5 (in /lib64/libc-2.17.so)
==14052== by 0x574DD51: _IO_default_uflow (in /lib64/libc-2.17.so)
==14052== by 0x5748729: getchar (in /lib64/libc-2.17.so)
==14052== by 0x4024C1: main (main.cpp:88)
==14052==
==14052== HEAP SUMMARY:
==14052== in use at exit: 16,468 bytes in 696 blocks
==14052== total heap usage: 2,924 allocs, 2,228 frees, 523,457 bytes allocated
==14052==
==14052== 96 (16 direct, 80 indirect) bytes in 1 blocks are definitely lost in loss record 10 of 18
==14052== at 0x4C29203: operator new(unsigned long) (vg_replace_malloc.c:334)
==14052== by 0x40442F: LinkedList<int>::insertHead(int) (LinkedList.h:58)
==14052== by 0x4034A0: void parse_instruction<int>(std::string, std::basic_ofstream<char, std::char_traits<char> >&, LinkedList<int>*) (main.cpp:101)
==14052== by 0x4023AC: main (main.cpp:67)
==14052==
==14052== 585 (16 direct, 569 indirect) bytes in 1 blocks are definitely lost in loss record 15 of 18
==14052== at 0x4C29203: operator new(unsigned long) (vg_replace_malloc.c:334)
==14052== by 0x403BEB: LinkedList<std::string>::insertHead(std::string) (LinkedList.h:58)
==14052== by 0x402C84: void parse_instruction<std::string>(std::string, std::basic_ofstream<char, std::char_traits<char> >&, LinkedList<std::string>*) (main.cpp:101)
==14052== by 0x402371: main (main.cpp:64)
==14052==
==14052== 15,528 (16 direct, 15,512 indirect) bytes in 1 blocks are definitely lost in loss record 18 of 18
==14052== at 0x4C29203: operator new(unsigned long) (vg_replace_malloc.c:334)
==14052== by 0x403DE3: LinkedList<std::string>::insertAfter(std::string, std::string) (LinkedList.h:94)
==14052== by 0x402DF6: void parse_instruction<std::string>(std::string, std::basic_ofstream<char, std::char_traits<char> >&, LinkedList<std::string>*) (main.cpp:111)
==14052== by 0x402371: main (main.cpp:64)
==14052==
==14052== LEAK SUMMARY:
==14052== definitely lost: 48 bytes in 3 blocks
==14052== indirectly lost: 16,161 bytes in 687 blocks
==14052== possibly lost: 0 bytes in 0 blocks
==14052== still reachable: 259 bytes in 6 blocks
==14052== of which reachable via heuristic:
==14052== stdstring : 259 bytes in 6 blocks
==14052== suppressed: 0 bytes in 0 blocks
==14052== Reachable blocks (those to which a pointer was found) are not shown.
==14052== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==14052==
==14052== For counts of detected and suppressed errors, rerun with: -v
==14052== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)
最佳答案
首先,我想鼓励您在数据结构方面进行培训,我认为这是学习编程的最佳方式,从指针和内存到分而治之算法和多线程应用程序。
现在,我发现您的代码没有严格遵循 Stackoverflow Minimum Reproducible Example guidelines ,因为它包含与泄漏无关的方法,如“at”、“toString”和“size”,并且没有提供可用于重现 valgrind 输出的案例。我建议您仔细关注他们,否则您将来可能会获得反对票。就我而言,我将利用它来尝试帮助您更多地改进您的 LinkedList 实现。
我看到的主要问题是 LinkedList 的析构函数什么都不做(只释放它自己使用的内存,而不是它的节点),所以如果你的程序在添加一个元素后结束,说:
int main() {
auto l = new LinkedList<int>();
l->insertHead(1);
// l->remove(1);
delete l;
}
1个节点(head)对应的内存会被泄露。我推荐的实现是:
~LinkedList() {
while (head != NULL) {
Node *nodeToDelete = head;
head = head->next;
delete nodeToDelete;
}
}
如果您在您创建的每个 LinkedList 上调用 delete,或者如果您觉得准备好了,您可以使用智能指针在 LinkedLists 超出范围时调用 delete,就好像您没有使用指针。但是对于它们,如果没有析构函数,您也会遇到泄漏,析构函数不能正确释放每个 LinkedList 节点。我希望这对你有帮助,如果你想了解更多并且有兴趣让你所有的 LinkedList 方法像你的教授期望的那样工作,下面我会给你其他建议。祝你好运。
另一方面,当您的 size 方法不为 null 时,它似乎不计算头部。我将其简化为:
int size() {
cout << "In size function" << endl;
int sizeOfList = 0;
Node *fakeIterator = head;
while (fakeIterator != NULL) {
++sizeOfList;
fakeIterator = fakeIterator->next;
}
return sizeOfList;
}
#include <memory>
int main() {
auto l = make_unique<LinkedList<int>>();
l->insertHead(1);
}
Valgrind 输出:
==3288== Memcheck, a memory error detector
==3288== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==3288== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==3288== Command: ./run
==3288==
In insertHead function
==3288==
==3288== HEAP SUMMARY:
==3288== in use at exit: 0 bytes in 0 blocks
==3288== total heap usage: 4 allocs, 4 frees, 73,760 bytes allocated
==3288==
==3288== All heap blocks were freed -- no leaks are possible
==3288==
==3288== For counts of detected and suppressed errors, rerun with: -v
==3288== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
关于c++ - 我对内存泄漏有什么不了解?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58863012/
我开始在 Ethereum blockchain 上了解如何开发智能合约以及如何写 web-script用于与智能合约交互(购买、销售、统计......)我得出了该怎么做的结论。我想知道我是否正确理解
我正在 UIView 中使用 CATransform3DMakeRotation,并且我正在尝试进行 45º,变换就像向后放置一样: 这是我拥有的“代码”,但显然没有这样做。 CATransform3
我目前正在测试 WebRTC 的功能,但我有一些脑逻辑问题。 WebRTC 究竟是什么? 我只读了“STUN”、“P2P”和其他...但是在技术方面什么是正确的 WebRTC(见下一个) 我需要什么
我在看 DelayedInit在 Scala in Depth ... 注释是我对代码的理解。 下面的 trait 接受一个非严格计算的参数(由于 => ),并返回 Unit .它的行为类似于构造函数
谁能给我指出一个用图片和简单的代码片段解释 WCF 的资源。我厌倦了谷歌搜索并在所有搜索结果中找到相同的“ABC”文章。 最佳答案 WCF 是一项非常复杂的技术,在我看来,它的文档记录非常少。启动和运
我期待以下 GetArgs.hs打印出传递给它的参数。 import System.Environment main = do args main 3 4 3 :39:1: Coul
private int vbo; private int ibo; vbo = glGenBuffers(); ibo = glGenBuffers(); glBindBuffer(GL_ARRAY_
我正在尝试一个 for 循环。我添加了一个 if 语句以在循环达到 30 时停止循环。 我见过i <= 10将运行 11 次,因为循环在达到 10 次时仍会运行。 如果有设置 i 的 if 语句,为什
我正在尝试了解 WSGI 的功能并需要一些帮助。 到目前为止,我知道它是一种服务器和应用程序之间的中间件,用于将不同的应用程序框架(位于服务器端)与应用程序连接,前提是相关框架具有 WSGI 适配器。
我是 Javascript 的新手,我正在尝试绕过 while 循环。我了解它们的目的,我想我了解它们的工作原理,但我在使用它们时遇到了麻烦。 我希望 while 值自身重复,直到两个随机数相互匹配。
我刚刚偶然发现Fabric并且文档并没有真正说明它是如何工作的。 我有根据的猜测是您需要在客户端和服务器端都安装它。 Python 代码存储在客户端,并在命令运行时通过 Fabric 的有线协议(pr
我想了解 ConditionalWeakTable .和有什么区别 class ClassA { static readonly ConditionalWeakTable OtherClass
关闭。这个问题需要更多focused .它目前不接受答案。 想改善这个问题吗?更新问题,使其仅关注一个问题 editing this post . 5年前关闭。 Improve this questi
我还没有成功找到任何可以引导我理解 UIPickerView 和 UIPickerView 模型的好例子。有什么建议吗? 最佳答案 为什么不使用默认的 Apple 文档示例?这是来自苹果文档的名为 U
我在看foldM为了获得关于如何使用它的直觉。 foldM :: Monad m => (a -> b -> m a) -> a -> [b] -> m a 在这个简单的例子中,我只返回 [Just
答案What are _mm_prefetch() locality hints?详细说明提示的含义。 我的问题是:我想要哪一个? 我正在处理一个被重复调用数十亿次的函数,其中包含一些 int 参数。
我一直在读这个article了解 gcroot 模板。我明白 gcroot provides handles into the garbage collected heap 然后 the handle
提供了一个用例: 流处理架构;事件进入 Kafka,然后由带有 MongoDB 接收器的作业进行处理。 数据库名称:myWebsite集合:用户 并且作业接收 users 集合中的 user 记录。
你好 我想更详细地了解 NFS 文件系统。我偶然发现了《NFS 图解》这本书,不幸的是它只能作为谷歌图书提供,所以有些页面丢失了。有人可能有另一个很好的资源,这将是在较低级别上了解 NFS 的良好开始
我无法理解这个问题,哪个更随机? rand() 或: rand() * rand() 我发现这是一个真正的脑筋急转弯,你能帮我吗? 编辑: 凭直觉,我知道数学答案是它们同样随机,但我忍不住认为,如果您
我是一名优秀的程序员,十分优秀!