【问题标题】:Memory allocation on C++ object creationC++ 对象创建时的内存分配
【发布时间】:2012-02-21 21:45:33
【问题描述】:

在下面C类的对象创建过程中观察到不同大小的内存分配,

class C {
 int i;
 int j;
};

void f() {
 C *c = new C;
 C *c2 = new C[2];
 C (*c3)[2] = new C[2][2];
}

c 分配了 8 个字节;

c2分配了8*2+4字节;

c3 分配有 8*2*2+4 字节。

为什么 c2 和 c3 需要多 4 个字节?

【问题讨论】:

  • 这是我自己的功课。:)
  • 你如何测量分配的内存量?
  • 在没有表明你至少已经尝试回答问题的情况下,不要在这里提出家庭作业问题。这对你的同学和像我这样花费自己的时间来帮助他人更多地了解编程和计算机科学的人来说是不诚实的。如果你尝试在工业界或学术界做这样的事情,可能会丢掉你的工作。
  • 我想你的意思是*c*c2*c3,分别是指针。
  • @Joshua Warner。我一直在使用objdump 并试图理解反汇编代码。 :(

标签: c++ object memory-management new-operator


【解决方案1】:

请记住,C++ 将内存分配对象表达式分开。默认的array-new 表达式T * p = new T[N]; 都为N 对象分配足够的内存 构造这些对象。在另一端,delete[] p; 必须调用所有这些元素的析构函数,然后释放内存。

虽然分配和释放内存由平台处理,并且可释放内存通过单个指针值被操作系统充分识别,但构造和销毁对象更加复杂。实际对象的数量必须存储在某个地方,为此,标准允许 C++ 实现请求比N * sizeof(T) 更多的内存。确实,指针p 将始终指向N 对象数组的开头,但p 不必与底层内存分配器返回的指针相同。 (实际上,p 可以保证正好是底层分配结果被多余内存抵消的值。)

细节完全由实施决定。不过,有些平台提供额外的保证;例如,Itanium ABI(将额外数据称为“数组 cookie”)表示new T[N] 的内存布局如下:

+- alignof(T) --+-- sizeof(T) --+-- sizeof(T) --+-- sizeof(T) --+-- ...
| ***** [8B: N] |  1st element  |  2nd element  |  3rd element  |  .....
+---------------+---------------+---------------+---------------+-- ...
A               A
|               |_ result of "new T[N]"
|
|_ value returned "operator new[]()"

【讨论】:

  • 感谢详细信息。我刚刚发现 32 位平台使用这些额外的 32/8=4 字节来存储由new [] 表达式分配的对象的总大小。
  • @Kerrek,如果我有一个 operator new[] (size_t n) 过载会发生什么 - 是否有任何保证 new C[2] 会给 n 正好是 2 * sizeof(C)?
  • @Andrey:不不,这无关。无论最终调用哪个数组新运算符,都将使用包含额外空间要求的大小参数调用。
  • 更准确地说,只有 POD 对象在所有平台上都有保证的内存布局。
【解决方案2】:

来自标准([expr.mew]部分):

new-expression 将请求的空间量作为std::size_t 类型的第一个参数传递给分配函数。该参数不应小于正在创建的对象的大小;只有当对象是一个数组时,它才可能大于正在创建的对象的大小。

显然,该标准希望将一些附加信息存储在动态分配的数组中。

现在,使用您的调试器查看这些额外字节中填充了哪些内容,并确定编译器何时可能需要这些额外信息来完成其工作。

(提示:修复您的程序,使其不会泄漏内存)

【讨论】:

    【解决方案3】:

    很多编译器使用 new[] 返回的指针前的 4 个字节来存储实际分配的对象数。这完全依赖于实现,重要的是要记住,将您带到分配的内存范围之外的指针算法会导致未定义的行为

    【讨论】:

      猜你喜欢
      • 2014-03-31
      • 2023-03-18
      • 1970-01-01
      • 2012-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-22
      相关资源
      最近更新 更多