C++ 上的内存分配对象创建

发布于 2024-12-29 16:53:06 字数 257 浏览 0 评论 0原文

下面在类 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个字节?

The different size of memory allocation is observed during the object creation on class C below,

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 is allocated with 8 bytes;

c2 is allocated with 8*2+4 bytes;

c3 is allocated with 8*2*2+4 bytes.

Why does c2 and c3 aquire 4 more bytes?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

固执像三岁 2025-01-05 16:53:06

请记住,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[]()"

Remember that C++ separates memory allocation and object expression. The default array-new expression T * p = new T[N]; both allocates enough memory for N objects and constructs those objects. At the other end, delete[] p; must call the destructor of all those elements, and then free the memory.

While allocating and freeing memory is handled by the platform, and freeable memory is sufficiently well identified to the OS by a single pointer value, constructing and destroying objects is more complicated. The number of actual objects must be stored somewhere, and to that end, the standard permits a C++ implementation to request more memory than N * sizeof(T). It is true that the pointer p will always point to the beginning of the array of N objects, but p does not have to be the same pointer that was returned by the underlying memory allocator. (In fact, p is guaranteed to be precisely the value of the underlying allocation result offset by the excess amount of memory.)

The details are entirely left up to the implementation. Some platforms provide additional guarantees, though; for example, the Itanium ABI (which calls the extra data "array cookie") says that the memory for new T[N] will be laid out as follows:

+- 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[]()"
简单 2025-01-05 16:53:06

根据标准([expr.mew] 部分):

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

显然,该标准期望使用动态分配的数组来存储一些附加信息。

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

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

From the standard (section [expr.mew]):

A new-expression passes the amount of space requested to the allocation function as the first argument of type std::size_t. That argument shall be no less than the size of the object being created; it may be greater than the size of the object being created only if the object is an array.

Clearly the standard expects some additional information to be stored with a dynamically allocated array.

Now, use your debugger to see what's stuffed into those extra bytes, and figure out when that extra information might be needed for the compiler to do its job.

(Hint: fix your program so that it doesn't leak memory)

坏尐絯℡ 2025-01-05 16:53:06

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

A lot of compilers use the 4 bytes before the pointer returned from new[] to store the number of objects actually being allocated. This is all implementation dependent and it's important to remember that pointer arithmetic that takes you outside the range of memory you allocated results in undefined behavior

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文