为什么新的第一次分配1040个额外的字节? [英] Why does new allocate 1040 extra bytes the first time?

查看:36
本文介绍了为什么新的第一次分配1040个额外的字节?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建这个简单的测试程序,以演示使用标准new ...分配内存时对齐的工作方式.

I was creating this simple test program to demonstrate the way alignment works when allocating memory using standard new...

#include <iostream>
#include <iomanip>
#include <cstdint>

//
// Print a reserved block: its asked size, its start address 
//       and the size of the previous reserved block
//
void print(uint16_t num, uint16_t size_asked, uint8_t* p) {
   static uint8_t* last = nullptr;

   std::cout << "BLOCK " << num << ":   ";
   std::cout << std::setfill('0') << std::setw(2) << size_asked << "b, "; 
   std::cout << std::hex << (void*)p;
   if (last != nullptr) {
      std::cout << ", " << std::dec << (uint32_t)(p - last) << "b";
   }
   std::cout << "\n";
   last = p;
}

int main(void) {
   // Sizes of the blocks to be reserved and pointers
   uint16_t s[8] = { 8, 8, 16, 16, 4, 4, 6, 6 };
   uint8_t* p[8];

   // Reserve some consecutive memory blocks and print
   // pointers (start) and their real sizes
//   std::cout << "          size   start    prev.size\n";
//   std::cout << "-----------------------------------\n";
   for(uint16_t i = 0; i < 8; ++i) {
      p[i] = new uint8_t[s[i]];
      print(i, s[i], p[i]);
   }

   return 0;
}

但是当我执行程序时,我发现了这种奇怪的行为:

But when I executed the program I found this odd behaviour:

[memtest]$ g++ -O2 mem.cpp -o mem
[memtest]$ ./mem 
BLOCK 0:   08b, 0xa0ec20
BLOCK 1:   08b, 0xa0f050, 1072b
BLOCK 2:   16b, 0xa0f070, 32b
BLOCK 3:   16b, 0xa0f090, 32b
BLOCK 4:   04b, 0xa0f0b0, 32b
BLOCK 5:   04b, 0xa0f0d0, 32b
BLOCK 6:   06b, 0xa0f0f0, 32b
BLOCK 7:   06b, 0xa0f110, 32b

如您所见,new分配的第二个块不在下一个32b存储器指定的地址,而是较远的位置(相距1040字节).如果这还不够奇怪,请取消注释打印出表头的2 std :: cout行,将产生以下结果:

As you can see, the second block allocated by new is not at the next 32b memory alligned address, but far away (1040 bytes away). If this is not odd enough, uncommenting the 2 std::cout lines that print out the header of the table, yields this result:

[memtest]$ g++ -O2 mem.cpp -o mem
[memtest]$ ./mem 
          size   start    prev.size
-----------------------------------
BLOCK 0:   08b, 0x1f47030
BLOCK 1:   08b, 0x1f47050, 32b
BLOCK 2:   16b, 0x1f47070, 32b
BLOCK 3:   16b, 0x1f47090, 32b
BLOCK 4:   04b, 0x1f470b0, 32b
BLOCK 5:   04b, 0x1f470d0, 32b
BLOCK 6:   06b, 0x1f470f0, 32b
BLOCK 7:   06b, 0x1f47110, 32b

这是正常的预期结果.是什么使新产品在首次运行时表现得如此奇怪?我正在使用g ++(GCC)7.1.120170516.您可能没有进行优化就进行编译,结果是相同的.

This is normal expected result. What makes new behave in such an odd way at first run? I am using g++ (GCC) 7.1.1 20170516. You may compile without optimizations and result is the same.

推荐答案

您会惊讶地发现,您的程序所做的不仅是分配一些内存,还有很多其他功能.

You'll be surprised to learn that your program does a lot more than just make a few memory allocations.

std::cout << "BLOCK " << num << ":   ";

您的程序还利用其内置的

Your program also generates formatted output to std::cout, making use of its built-in std::streambuf.

很明显, std :: cout 的第一个输出为内部 std :: streambuf 分配了一个1024字节的缓冲区.这发生在您第一次分配 new 之后,而第二次分配之前.缓冲区仅在第一次使用时才需要分配一次.

It appears rather obvious that the first output to std::cout allocates a 1024 byte buffer for the internal std::streambuf. This happens after your first new allocation, and before your second one. The buffer only needs to be allocated once, the first time it's used.

尽管不用说内部存储器分配的细节是高度实现定义的,但这似乎是您情况下最可能的解释.

Although it goes without saying that the particulars of internal memory allocations are highly implementation-defined, this seems to be the most likely explanation in your case.

这篇关于为什么新的第一次分配1040个额外的字节?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆