C++ 链表类中的内存泄漏
如果我在VisualStudio中运行它,它会告诉我存在内存泄漏,但我没有发现析构函数有任何问题。我做错了什么?是因为内存泄漏函数在析构函数之前被调用吗?我不应该在最后调用内存泄漏函数吗 我已经在codereview上发布了这个,他们说它工作得很好,但我当时没有包括析构函数。我现在加了一个,但我不确定它是否真的有效C++ 链表类中的内存泄漏,c++,C++,如果我在VisualStudio中运行它,它会告诉我存在内存泄漏,但我没有发现析构函数有任何问题。我做错了什么?是因为内存泄漏函数在析构函数之前被调用吗?我不应该在最后调用内存泄漏函数吗 我已经在codereview上发布了这个,他们说它工作得很好,但我当时没有包括析构函数。我现在加了一个,但我不确定它是否真的有效 #define _CRTDBG_MAP_ALLOC #include <stdlib.h> #include <crtdbg.h> #include <
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
struct node {
int key;
struct node *next;
};
class linked_list {
private:
struct node *head;
struct node *tail;
public:
linked_list() {
head = nullptr;
tail = nullptr;
}
void create(int key) {
struct node *temp;
temp = new struct node;
temp->key = key;
temp->next = nullptr;
head = temp;
tail = head;
}
void insert(int key) {
if (key < head->key) {
insert_beginning(key);
}
else if ((head->next == nullptr) || (key > tail->key)) {
insert_end(key);
}
else {
insert_middle(key);
}
}
void insert_beginning(int key) {
if (head->next == nullptr) {
tail = head;
}
struct node *temp;
temp = new struct node;
temp->key = key;
temp->next = head;
head = temp;
}
void insert_end(int key) {
struct node *temp;
temp = new struct node;
temp->key = key;
temp->next = nullptr;
if (head->next == nullptr) {
head->next = temp;
tail = temp;
}
else {
tail->next = temp;
}
tail = temp;
}
void insert_middle(int key) {
struct node *temp;
temp = new struct node;
temp->key = key;
struct node *current = head;
struct node *prev = current;
while (current->key < temp->key) {
prev = current;
current = current->next;
}
prev->next = temp;
temp->next = current;
}
void delete_node(int key) {
if (head == nullptr) {
cout << "List is empty\n";
return;
}
if (head->key == key) {
if (head->next == nullptr) {
delete(head);
head = tail = nullptr;
}
struct node *temp = head;
head = head->next;
delete(temp);
}
else {
struct node *current = head;
struct node *prev = current;
while ((current->key != key) && (current->next != nullptr)) {
prev = current;
current = current->next;
}
if ((current->key != key) && (current->next == nullptr)) {
cout << "Key not found\n";
}
else if ((current->key == key) && (current->next == nullptr)) {
tail = prev;
prev->next = nullptr;
delete(current);
}
else {
prev->next = current->next;
delete(current);
}
}
}
void search_node(int key) {
if (head->key == key || tail->key == key) {
cout << "Node found\n";
return;
}
struct node *current = head;
while ((current->key != key) && (current->next != nullptr)) {
current = current->next;
}
if (current->key == key) {
cout << "Node found\n";
}
else {
cout << "Node not found\n";
}
}
void print_nodes(void) {
struct node *current = head;
while (current != nullptr) {
cout << current->key << '\n';
current = current->next;
}
}
~linked_list() {
struct node *current = head;
struct node *prev = current;
while (current->next != nullptr) {
current = current->next;
delete(prev);
prev = current;
}
delete(prev);
}
};
int main(void) {
linked_list list;
list.create(0);
for (int i = 1; i < 20; ++i) {
list.insert(i);
}
list.search_node(5);
list.search_node(0);
list.search_node(-1);
list.delete_node(19);
list.delete_node(0);
list.print_nodes();
_CrtDumpMemoryLeaks();
}
\define\u CRTDBG\u MAP\u ALLOC
#包括
#包括
#包括
使用std::cout;
使用std::cin;
使用std::endl;
结构节点{
int键;
结构节点*下一步;
};
类链表{
私人:
结构节点*头部;
结构节点*尾部;
公众:
链表(){
水头=零PTR;
tail=nullptr;
}
void创建(int键){
结构节点*temp;
temp=新结构节点;
温度->键=键;
temp->next=nullptr;
压头=温度;
尾=头;
}
无效插入(整数键){
如果(键<头->键){
插入_开头(键);
}
如果((head->next==nullptr)| |(key>tail->key)){
插入_端(键);
}
否则{
插入_中间(键);
}
}
无效插入_开头(int键){
if(head->next==nullptr){
尾=头;
}
结构节点*temp;
temp=新结构节点;
温度->键=键;
温度->下一步=头部;
压头=温度;
}
无效插入\u结束(int键){
结构节点*temp;
temp=新结构节点;
温度->键=键;
temp->next=nullptr;
if(head->next==nullptr){
头部->下一步=温度;
尾=温度;
}
否则{
尾部->下一步=温度;
}
尾=温度;
}
无效插入_中间(int键){
结构节点*temp;
temp=新结构节点;
温度->键=键;
结构节点*当前=头部;
结构节点*prev=当前;
同时(当前->按键<临时->按键){
prev=当前值;
当前=当前->下一步;
}
上一个->下一个=温度;
温度->下一步=当前;
}
void delete_节点(int键){
if(head==nullptr){
cout key==key){
if(head->next==nullptr){
删除(标题);
头=尾=空PTR;
}
结构节点*温度=头部;
头部=头部->下一步;
删除(临时);
}
否则{
结构节点*当前=头部;
结构节点*prev=当前;
while((当前->键!=key)&&(当前->下一步!=nullptr)){
prev=当前值;
当前=当前->下一步;
}
如果((当前->键!=键)&&(当前->下一步==空PTR)){
cout key==key)&&(当前->下一步==nullptr)){
尾部=上一个;
prev->next=nullptr;
删除(当前);
}
否则{
上一个->下一个=当前->下一个;
删除(当前);
}
}
}
无效搜索节点(int键){
如果(头->键==键| |尾->键==键){
cout key!=key)&&(当前->下一步!=nullptr)){
当前=当前->下一步;
}
如果(当前->键==键){
下一步;
删除(上一页);
prev=当前值;
}
删除(上一页);
}
};
内部主(空){
链表;
列表。创建(0);
对于(int i=1;i<20;++i){
清单.插入(i);
}
列表搜索节点(5);
列表。搜索_节点(0);
list.search_节点(-1);
列表。删除_节点(19);
列表。删除_节点(0);
list.print_nodes();
_CrtDumpMemoryLeaks();
}
当您调用\u CrtDumpMemoryLeaks();
时,您尚未销毁您的列表
对象
更新
添加一组大括号,以便在执行内存泄漏诊断之前销毁list
int main(void) {
{
linked_list list;
list.create(0);
for (int i = 1; i < 20; ++i) {
list.insert(i);
}
list.search_node(5);
list.search_node(0);
list.search_node(-1);
list.delete_node(19);
list.delete_node(0);
list.print_nodes();
}
_CrtDumpMemoryLeaks();
}
int main(无效){
{
链表;
列表。创建(0);
对于(int i=1;i<20;++i){
清单.插入(i);
}
列表搜索节点(5);
列表。搜索_节点(0);
list.search_节点(-1);
列表。删除_节点(19);
列表。删除_节点(0);
list.print_nodes();
}
_CrtDumpMemoryLeaks();
}
当您调用\u CrtDumpMemoryLeaks();
时,您尚未销毁您的列表
对象
更新
添加一组大括号,以便在执行内存泄漏诊断之前销毁list
int main(void) {
{
linked_list list;
list.create(0);
for (int i = 1; i < 20; ++i) {
list.insert(i);
}
list.search_node(5);
list.search_node(0);
list.search_node(-1);
list.delete_node(19);
list.delete_node(0);
list.print_nodes();
}
_CrtDumpMemoryLeaks();
}
int main(无效){
{
链表;
列表。创建(0);
对于(int i=1;i<20;++i){
清单.插入(i);
}
列表搜索节点(5);
列表。搜索_节点(0);
list.search_节点(-1);
列表。删除_节点(19);
列表。删除_节点(0);
list.print_nodes();
}
_CrtDumpMemoryLeaks();
}
使用MSVC尽可能晚地进行泄漏检查的常用方法是启用自动转储功能,代码如下:
_CRTSETDBGLAG(_CRTSETDBGLAG(_CRTDBG_报告_标志)| CRTDBG_泄漏检查_DF)
这将在main/WinMain返回且全局对象析构函数运行后执行泄漏检查。如果您曾经看到MFC转储报告,则说明它是如何启用的。使用MSVC尽可能晚地执行泄漏检查的常用方法是启用自动转储功能,代码如下: _CRTSETDBGLAG(_CRTSETDBGLAG(_CRTDBG_报告_标志)| CRTDBG_泄漏检查_DF)