【发布时间】:2011-05-14 02:40:41
【问题描述】:
考虑以下 C++ 程序:
#include <cstdlib> // for exit(3)
#include <string>
#include <iostream>
using namespace std;
void die()
{
exit(0);
}
int main()
{
string s("Hello, World!");
cout << s << endl;
die();
}
通过 valgrind 运行它会显示这一点(为简洁起见,修剪了一些输出):
==1643== HEAP SUMMARY:
==1643== in use at exit: 26 bytes in 1 blocks
==1643== total heap usage: 1 allocs, 0 frees, 26 bytes allocated
==1643==
==1643== LEAK SUMMARY:
==1643== definitely lost: 0 bytes in 0 blocks
==1643== indirectly lost: 0 bytes in 0 blocks
==1643== possibly lost: 26 bytes in 1 blocks
==1643== still reachable: 0 bytes in 0 blocks
==1643== suppressed: 0 bytes in 0 blocks
如您所见,在堆上分配的 26 个字节有可能丢失。我知道std::string 类有一个 12 字节的结构(至少在我的 32 位 x86 架构和 GNU 编译器 4.2.4 上)和“Hello,World!”带有空终止符的有 14 个字节。如果我理解正确的话,这个 12 字节的结构包含一个指向字符串的指针、分配的大小和引用计数(如果我在这里错了,请有人纠正我)。
现在我的问题是:C++ 字符串是如何存储在堆栈/堆中的? std::string(或其他 STL 容器)在声明时是否存在堆栈对象?
附:我在某处读到 valgrind 可能在一些使用 STL 容器(和“几乎容器”,例如 std::string)的 C++ 程序中报告内存泄漏的误报。我不太担心这种泄漏,但它确实激起了我对 STL 容器和内存管理的好奇心。
【问题讨论】:
-
@EboMike:我编写了
die()函数将exit(0)调用与main()分开。我的程序现在必须将控制权转移给一个被调用的函数,其中exit(0)函数在该程序的执行中“拔掉插头”。请记住,除了学术原因之外,该计划没有任何用处。 -
我的意思是 die() 首先导致泄漏。如果你一心想在里面放一个 die(),至少把字符串放到它自己的范围内。
-
换句话说,“我射中了自己的脚,然后我泄了气。”我的建议 - 使用止血带。
标签: c++ string memory-leaks