全球宣布时内存泄露?
memory leaked when globaly declared?
如果不是将指针声明为 main 的一部分,而是全局声明它们,这段代码是否仍然会泄漏? 我用Valgrind memcheck测试过,它没有
class Test1 {
public:
Test1() { std::cout << "Constructor of Test " << std::endl; }
~Test1() { std::cout << "Destructor of Test " << std::endl; }
};
//Memory leaked or not when globally declared?
// Test1 *t1;
// Test1 *t2;
// Test1 *t;
int main()
{
//mem will leak if not deallocated later
Test1 *t1;
Test1 *t2;
Test1 *t;
try {
t1=new Test1[100];
t2=new Test1;
t =new Test1;
throw 10;
}
catch(int i)
{
std::cout << "Caught " << i << std::endl;
// delete []t1;
// delete t;
// delete t2;
}
return 0;
}
声明变量全局将使指针变量全局,而不是指针指向的内容(它已经是全局的,因为它位于堆上(。
因此,您当前的实现也存在泄漏。
局部变量在超出范围时会被销毁,但它们指向的内容不会自动输出。建议:忘记完整性new
和delete
运算符,使用 STL 或智能指针。
编辑:你在问为什么valgrind没有检测到它,这是一个与原始问题不同的问题(我编辑以添加标签(。
现在你总是在泄漏内存,无论你是在 main 还是全局中声明指针。
每当在代码中使用new
时,都需要使用delete
或delete[]
。
在现代C++中,使用new
被认为是一种不好的做法,如果你想要一个数组,你应该使用std::vector
,或者如果你正在管理指向对象的指针,你应该使用std::unique_ptr
。
正如在其他答案中已经提到的,分配对象的析构函数不会在程序的两个变体中调用,指针的范围和生存期不会影响点头会发生什么,但您已经通过在析构函数中打印来证明这一点。
然而,瓦尔格林德的报告略有不同。
我使用较短的 2 个元素数组运行以减少输出量。
堆摘要告诉您运行结束时堆上保留哪些数据,对于两个程序是相同的:
==397== HEAP SUMMARY:
==397== in use at exit: 12 bytes in 3 blocks
==397== total heap usage: 6 allocs, 3 frees, 76,944 bytes allocated
这意味着两个程序都不会释放对象。
然而,Valgrind 确实在"绝对丢失"分配(不引用任何变量中剩余的内存块(和"仍可访问"分配(保留引用(之间产生了差异。
带有本地指针的泄漏摘要
==397== LEAK SUMMARY:
==397== definitely lost: 12 bytes in 3 blocks
==397== indirectly lost: 0 bytes in 0 blocks
==397== possibly lost: 0 bytes in 0 blocks
==397== still reachable: 0 bytes in 0 blocks
==397== suppressed: 0 bytes in 0 blocks
带有全局指针的泄漏摘要
==385== LEAK SUMMARY:
==385== definitely lost: 0 bytes in 0 blocks
==385== indirectly lost: 0 bytes in 0 blocks
==385== possibly lost: 0 bytes in 0 blocks
==385== still reachable: 12 bytes in 3 blocks
==385== of which reachable via heuristic:
==385== length64 : 10 bytes in 1 blocks
如果指针是本地的,valgrind 可以确定没有引用保留,因为在主返回之后,堆栈位置不再有效。
如果指针是全局的,它们仍然有效,因此仍然可以使用或解除分配。
为什么瓦尔格林德要做出这种区分?
特别是在历史的 C 程序中,分配一些内存并在整个执行过程中使用它可能是合法的,而无需稍后释放内存。一旦程序退出,操作系统将清理程序的整个虚拟内存空间。因此,虽然这可能是一个错误,但它也可能是故意的。 如果您对此类泄漏感兴趣,valgrind 本身会告诉您必须如何调用才能看到它们:
==405== Reachable blocks (those to which a pointer was found) are not shown.
==405== To see them, rerun with: --leak-check=full --show-leak-kinds=all
然而,"绝对丢失"的记忆总是可疑的,这就是瓦尔格林德区分这些案例的原因。像valgrind这样的工具的价值在于它的精度。仅仅报告许多实际错误是不够的,为了有用,还必须努力产生少量的误报,否则查看报告通常会浪费开发人员的时间。
在现代C++中,泄漏内存的借口并不多,因为std::unique_ptr
应该是分配动态对象的方式。std::vector
应该尽可能用于动态数组和本地对象,因为编译器永远不会忘记释放。即使对于单例,valgrind 和地址清理器等工具输出中的噪声通常也会超过保存一个析构函数调用或释放的通常微不足道的好处。
- WinVerifyTrust 仅在使用文件而不是内存 blob 时才有效
- 当另一个数组是内存集时,内存集是否会更改数组长度?
- 当注入程序的内存空间时,如何读取从 0 到 0xFFFFFFFFF 的每个字节?我正在创建模式扫描仪
- 当 C 和 C++ 中严格要求内存释放时
- 当有大量内存分配时,如何处理C++编程中的异常
- 在内存映射时写入内存映射的文件
- 使用 AMD 的 Vulkan 内存分配器时出现链接器错误 (LNK2005)
- 处理内存分配时的保护标志
- C++ 分配器在内存不足时使应用程序崩溃
- C++ : 内存不足时应返回什么?
- 开发C++在运行大内存程序时崩溃
- 简单加密程序集程序-写入内存位置时发生访问冲突
- 写入内存缓冲区时性能损失 (C++)
- 写入共享内存队列时出现隔离错误
- 检测"内存泄漏"时,瓦尔格林德的真实指针是什么?
- 评估 C/C++ 内存泄漏时的虚拟与物理内存
- 如何正确管理内存(运行时)C++
- 获取加载到内存中时DLL或EXE的代码段的大小
- 当内存泄漏时,如果程序再次运行,是否可以将其插入
- 进行内存释放时出现调试错误