gpt4 book ai didi

c++ - 删除分配给列表的内存

转载 作者:行者123 更新时间:2023-11-28 00:51:33 24 4
gpt4 key购买 nike

看看下面的代码。在这段代码中,开始执行时内存使用量为 1020K。但在执行结束时内存使用量为 1144K。有人可以帮我确定内存泄漏。如果 func() 被调用五次,内存使用量将达到 1500K+。如果我们不使用列表,内存使用量不会增加。

void func();

int _tmain(int argc, _TCHAR* argv[])
{
func();
return 0;
}

void func()
{
list<char*> list1;
list<char*>::iterator iter;
char* val;
for(int i=0; i<100000; i++)
{
val = new char[20];
for(int j=0; j<20;j++)
{
val[j] = 'A';
}
val[19] = '\0';
list1.push_back(val);
}

iter = list1.begin();
for(int k=0; k<100000;k++, iter++)
{
delete[] *iter;
*iter = NULL;
}
val = NULL;

list1.clear();
list1.empty();
}

最佳答案

我在这里没有看到内存泄漏,但我确实看到了很多非常糟糕的代码。

我在您的代码中看到一些提示,表明您正在 Windows 下运行,当我凝视我的 Crystal 球时,我想我看到您正在检查任务管理器以检测内存泄漏。使用任务管理器检测内存泄漏就像用大刀做手术。 TM 可能会提示您系统中可能存在大量内存泄漏,但它与您的程序相距太远,而且太粗略以至于无法确定。您需要使用专用于该工作的工具,而不是使用 TM 来确定是否存在内存泄漏。 Visual Studio has such a tool内置。

当我在您的代码中使用这些内置工具时:

#include <cstdlib>
#include <list>
using std::list;

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>


void func();

int main(int argc, char* argv[])
{
func();
return 0;
}

void func()
{
list<char*> list1;
list<char*>::iterator iter;
char* val;
for(int i=0; i<100000; i++)
{
val = new char[20];
for(int j=0; j<20;j++)
{
val[j] = 'A';
}
val[19] = '\0';
list1.push_back(val);
}

iter = list1.begin();
for(int k=0; k<100000;k++, iter++)
{
delete[] *iter;
*iter = NULL;
}
val = NULL;

list1.clear();
list1.empty();

_CrtDumpMemoryLeaks();
}

...我明白了:

Detected memory leaks!
Dumping objects ->
{142} normal block at 0x00000000000778C0, 24 bytes long.
Data: < x x > C0 78 07 00 00 00 00 00 C0 78 07 00 00 00 00 00
{141} normal block at 0x0000000000077840, 16 bytes long.
Data: <( h > 28 F7 1A 00 00 00 00 00 68 F7 1A 00 00 00 00 00
Object dump complete.

共有 40 个字节报告了两次内存泄漏,因此这里没有广泛的内存泄漏。此外,这些可能是误报,报告诸如 CRT 的静态内存分配之类的事情,应该被忽略。

但是,正如我所说,我确实看到了很多非常糟糕的代码。这不是内存泄漏的原因,但它们很容易出现在实际代码中。

  1. 您使用了很多 magic numbers 。例如 for(int i=0; i<100000; i++) ,而不是你应该迭代列表(for( list<char*>::iterator it = list1.begin(); it != list1.end(); ++it)),或者至少询问列表它有多少元素(for( size_t i = 0; i < list1.size(); ++i ))

  2. 您正在使用动态分配/取消分配。在您确实需要动态分配的情况下,您应该改为使用 RAII,但应尽可能完全避免动态分配。在你的情况下,而不是 list<char*> , 你应该有一个 list<std::string>相反。

  3. 您在可以使用标准库提供的算法的地方使用手写循环。你从不写的代码是最可靠的代码。而不是内部循环初始化一个字符数组,只需执行 std::string s(20,'A') , 而不是外循环设置每个列表成员,使用类似 copy 的东西或 transform .

编辑 这是您的函数的重构版本,它解决了我上面提到的其中一些问题:

#include <string>
using std::string;
#include <algorithm>
using std::generate_n;
#include <iterator>
using std::back_inserter;

void func()
{
static const size_t NumStrings = 10000;
typedef list<string> strings;

// Populate the list
strings list2;
generate_n(back_inserter(list2), NumStrings, []() -> string
{
static const size_t NumChars = 19;
static const char InitChar = 'A';
return string(NumChars, InitChar);
});

// Clear the list
list2.clear();

// Done
_CrtDumpMemoryLeaks();
}

调用generate_n使用 C++11 lambda,但可以很容易地重构为完全使用仿函数或其他东西。

关于c++ - 删除分配给列表的内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13819451/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com