c++指针内存泄漏
Memory Leak with Pointers C++
我是c++新手,我发现我已经被Java和较新的编程语言(如Swift)宠坏了。所以我理解有时候你必须在c++中手动删除对象,比如指针。可以使用delete
关键字,也可以使用智能指针。但我很困惑,它是否删除了指针本身,所以指针不能再指向,或者它是否删除了指针指向的地方。
我正在编写的代码,作为一个整数链表。所以我有一个指针指向列表的头和尾。当有人"投票"某事时,它应该从列表中删除它,然后相应地重置头部(或尾部)。所以我有一些代码可以很好地完成我需要它做的事情:
int IntegerLinkedList::pollFirst(){
if (tail == nullptr && head == nullptr) {
return 0;
} else if (head == tail) {
int ret = head->getData();
head = nullptr;
tail = nullptr;
//delete head;
//delete tail;
return ret;
} else {
IntegerNode* newHead = head->getNext();
head->setNext(nullptr);
newHead->setPrevious(nullptr);
int ret = head->getData();
//delete head;
head = newHead;
return ret;
}
}
但是我从来没有真正删除它所指向的对象,我只是删除了所有指向它的指针。这会像在Java中那样删除对象吗?或者我必须手动删除它,我该怎么做?我的记忆泄露了吗??非常感谢
更新头部的代码也是
void IntegerLinkedList::addFirst(int x){
IntegerNode* n = new IntegerNode(x);
if (head == nullptr && tail == nullptr) {
head = n;
tail = n;
} else {
head->setPrevious(n);
n->setNext(head);
head = n;
}
}
头部在header中定义为
IntegerNode* head;
Java有一个垃圾收集器,基本上做智能指针做什么。也就是说,当对象的最后一个引用超出作用域时,清理内存。
delete
关键字释放指针指向的位置的内存。它实际上不对指针变量本身做任何事情(它只是一个地址)。
纠正你的代码的方法是:
else if (head == tail) { // suppose head = 0xAD4C0080
int ret = head->getData();
delete tail; // cleans memory at 0xAD4C0080, head and tail are still 0xAD4C0080
head = nullptr; // now head = 0
tail = nullptr; // now tail = 0
return ret;
} else {
IntegerNode* newHead = head->getNext();
head->setNext(nullptr);
newHead->setPrevious(nullptr);
int ret = head->getData(); // obtain data while head still exists
delete head; // get rid of head
head = newHead; // remove stray reference to deleted memory
return ret;
}
如果在这些示例中调用delete
后尝试使用值0xAD4C0080
,则会出现分段错误。
至于智能指针(引用你的评论):
是智能指针,但是它们会删除它所指向的内容还是只删除它们自己
智能指针在自身被解构时(通常是在超出作用域的情况下)删除它们所指向的对象。例如
void func() {
std::unique_ptr<int> pInt(new int);
} // pInt falls out of scope, std::unique_ptr<int>::~std::unique_ptr<int>() called
我很困惑是否删除指针本身,所以指针不能再次指向,或者如果它删除指针所在的位置指向.
删除指针所指向的对象。该指针必须指向一个被分配了动态作用域(new
关键字)的对象。
我只是删除了所有指向它的指针。那样会删除对象吗在Java中呢?
当然不是。
或者我必须手动删除它,我该怎么做?我内存泄漏?
你必须手动删除它,使用delete
关键字,是的,你正在泄漏内存,除非你这样做。
人们常说,从头开始学习c++比如果你已经知道Java,尝试学习c++要容易得多。c++对象的工作原理与Java中的根本不同。
不仅不同,而且在Java中根本没有对应的方式。例如,在Java中没有与c++中自动作用域实例化的对象等量物。
c++类实例的各种作用域的完整解释不能在stackoverflow.com上给出一个简短的回答。你需要找一本关于c++的好书,然后开始读。
忘记你所知道的关于Java类的一切。c++类不是这样工作的。你用Java做类比的时间越长,你学习如何正确使用c++类的时间就越长。
是的,使用智能指针可以帮助解决一些问题,它可以解决一些痛点。但是理解智能指针本身也需要完全理解c++的类模型。智能指针并不能解决所有问题,为了理解智能指针解决了什么问题,不能解决什么问题,理解c++类是如何工作的是很重要的。
这取决于头和尾的类型。在c++中,有操作符(例如operator=),也有析构函数。这可能会导致一些有趣的结果。举个例子:
#include <memory>
int main() {
// allocate memory
int* ptr = new int;
// store in smart pointer
std::unique_ptr<int> smart_ptr(ptr);
// create another wrapped pointer
std::unique_ptr<int> smart_ptr2(new int);
// throw away location of allocated memory
ptr = nullptr;
// free memory by assigning to smart pointer
smart_ptr = nullptr;
// we can call delete safely here because ptr is null
delete ptr;
// data pointed to by smart_ptr2 will
// be deleted at end of scope
return 0;
}
此外,还有两个用于分配内存的操作符,operator new和operator new[],必须分别使用delete和delete[]释放它们。
对这些概念的更详细的解释可能超出了本网站的范围。
我内存泄漏吗??
是的,如果你new
某事,你必须在某处delete
。将指针赋值给nullptr
不会影响已分配的数据。
但是我很困惑是否删除指针本身,所以指针不能再次指向,或者如果它删除指针所指向的位置。
delete
关键字将删除您发送给它的地址的内容。它不会删除命名变量,因为堆栈上的变量在作用域结束时被销毁。手动删除带有自动存储的内容导致undefined behaviour
。
我看到你对std::unique_ptr
感到困惑,不,他们没有删除自己。像任何其他变量一样,调用它们的析构函数并对变量进行析构。关于std::unique_ptr
的事情是,在它们的析构函数中,它们删除了它们指向的数据,而你必须自己删除它。您应该阅读有关RAII的知识。
你的代码有个问题,尤其是这几行:
head = nullptr;
tail = nullptr;
delete head;
delete tail;
这不会做任何事情。您没有删除任何数据,因为head
和tail
不指向任何数据。由于delete
关键字删除了数据指针所指向的数据,因此它不会删除任何内容。
但是,以std::unique_ptr
:
{
std::unique_ptr<int> myPtr;
myPtr = std::make_unique<int>(); // or you can use `new int;`
myPtr = nullptr; // The old int you allocated with `std::make_unique` is deleted.
myPtr = std::make_unique<int>(); // assign a newly allocated int
}
// Here, myPtr will free his data as it leaves the scope.
如果您使用new
关键字,那么您总是需要使用delete
。使用new
分配的内存不受管理。
当前您的程序在pollFirst
方法中泄漏内存,因为您在重新分配head
和tail
之前没有释放它们指向的内存。您可以通过在重新分配前调用delete head
和delete tail
来实现这一点。
如果你想要自动管理指针指向的内存,你应该考虑使用一种智能指针类型,比如unique_ptr
。
关于c++有几件事你应该知道。
- 析构函数(DTOR):析构函数是你为你的类定义的东西。如果你不定义析构函数,编译器会为你定义。
- 当你对一个指针调用delete时,这个类的DTOR被调用,它做必要的清理。为了测试它,请在DTOR中设置一个断点并运行代码。一旦控件命中DTOR,检查调用堆栈,您将发现调用堆栈中DTOR下面的最后一帧是您调用delete的行。
- 就智能指针而言,它的作用类似于垃圾收集器。智能指针有一个叫做引用计数的东西。当智能指针的引用计数变为0时,调用DTOR
注意:如果在类中有一个指针数据成员,建议编写自己的DTOR
- C++功能泄漏内存,我是C++新手,不确定如何解决
- 我的堆栈弹出式磁带的实现是否泄漏内存?
- 将 c++ 向量转换为字符 ** 而不会泄漏内存
- 析构函数 C++ 使泄漏内存
- 构造函数对象赋值是否泄漏内存
- corba :: orb_init泄漏内存
- Gmock泄漏内存
- 如何在不泄漏内存的情况下删除链接列表
- Visual C ODBC关闭记录集泄漏内存
- 为什么泄漏内存比在动态数组上执行 delete[] 慢
- OpenGL正在泄漏内存.哪个对象未释放
- 可以std ::退出泄漏内存
- uiautomation findall泄漏内存
- 为什么在此OpenCL代码中泄漏内存,为什么要泄漏内存
- pthread在完成后会泄漏内存
- win32 标准::线程泄漏内存
- 返回指向同一变量的指针是否会泄漏内存
- 使用clectType(new any_type())可能会泄漏内存泄漏
- Windows开发:如何确定我的应用程序是否正在泄漏内存
- WinHttp打开泄漏内存