Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C/C++;-为什么当我';m为单个int分配空间?_C++_C_Gdb_Heap - Fatal编程技术网

C++ C/C++;-为什么当我';m为单个int分配空间?

C++ C/C++;-为什么当我';m为单个int分配空间?,c++,c,gdb,heap,C++,C,Gdb,Heap,我目前正在使用gdb来查看低级代码的效果。现在我正在做以下工作: int* pointer = (int*)calloc(1, sizeof(int)); 然而,当我在gdb中使用info-proc-mappings检查内存时,我在.text部分之后看到了以下内容(因为Objfile显示了我正在调试的二进制文件的名称): 当我只为一个int分配空间时,堆为什么会那么大 最奇怪的是,即使我在执行calloc(1000,sizeof(int))时,堆的大小仍然保持不变 PS:我在x86_64机器上

我目前正在使用gdb来查看低级代码的效果。现在我正在做以下工作:

int* pointer = (int*)calloc(1, sizeof(int));
然而,当我在gdb中使用
info-proc-mappings
检查内存时,我在.text部分之后看到了以下内容(因为Objfile显示了我正在调试的二进制文件的名称):

当我只为一个int分配空间时,堆为什么会那么大

最奇怪的是,即使我在执行
calloc(1000,sizeof(int))
时,堆的大小仍然保持不变

PS:我在x86_64机器上运行Ubuntu 14.04。我用G++编译源代码(是的,我知道我不应该在C++中使用CaloC,这只是一个测试)。 当我只为一个int分配空间时,堆为什么会那么大

我在Linux上做了一个简单的测试。当调用
calloc
glibc在某个点调用sbrk()以从操作系统获取内存时:

(gdb) bt
#0  0x0000003a1d8e0a0a in brk () from /lib64/libc.so.6
#1  0x0000003a1d8e0ad7 in sbrk () from /lib64/libc.so.6
#2  0x0000003a1d87da49 in __default_morecore () from /lib64/libc.so.6
#3  0x0000003a1d87a0aa in _int_malloc () from /lib64/libc.so.6
#4  0x0000003a1d87a991 in malloc () from /lib64/libc.so.6
#5  0x0000003a1d87a89a in calloc () from /lib64/libc.so.6
#6  0x000000000040053a in main () at main.c:6
但是,
glibc
并没有要求操作系统精确获取您要求的4个字节<代码>glibc计算其自身的大小。glibc是这样做的:

  /* Request enough space for nb + pad + overhead */
  size = nb + mp_.top_pad + MINSIZE;
mp_u.top_upad默认为128*1024字节,因此这是当您请求4字节时系统分配0x21000字节的主要原因

您可以通过调用
mallopt
来调整mp_u.top_u键盘。这是mallopt的文件:

M_TOP_PAD

This parameter defines the amount of padding to employ when
calling sbrk(2) to modify the program break.  (The measurement
unit for this parameter is bytes.)  This parameter has an
effect in the following circumstances:

*  When the program break is increased, then M_TOP_PAD bytes
 are added to the sbrk(2) request.

In either case, the amount of padding is always rounded to a
system page boundary.
所以我更改了你的程序并添加了mallopt:

#include <stdlib.h>
#include <malloc.h>
int main()
{
  mallopt(M_TOP_PAD, 1);
  int* pointer = (int*)calloc(1, sizeof(int));
  return 0;
}
现在堆是4096字节。与我的页面大小完全相同:

(gdb) !getconf PAGE_SIZE
4096
有用链接:


既然您提到了C/C++,最好使用以下结构:

int* pointer = new int(1);

当您以后可能很想分配更多空间时,为什么系统要推测性地分配少量内存?不仅可能需要更多空间,而且很可能您需要更多空间。@user3688293:堆是一种类似数组或链表的数据结构,与链表一样,它有下一个元素指针,等等。这些必须与您的数据一起存储。使用像单个
int
这样的小分配实际上是非常浪费的。现在,这种浪费还不足以解释堆为什么从132 kB开始。这更多地与从操作系统请求内存的成本有关。您的C库分配器一次从操作系统中获取大块数据,以避免频繁支付该成本。Ben所描述的是大多数实现的典型情况。运行时可能会实现一个子分配器,它通过系统调用获取一个相当大的最小堆块,并使用自己的子分配算法将其分配给较小的请求。大多数运行时都是以这样或那样的形式进行的,因为系统堆管理在历史上是非常昂贵的。这样做会影响性能吗?我想如果你设置这个,它必须更频繁地调用sbrk?我认为这可能会影响性能。这是来自doc:
修改M_TOP_PAD是增加系统调用次数(当参数设置为低时)和在堆顶部浪费未使用的内存(当参数设置为高时)之间的折衷。
是的,但是OP想知道为什么calloc分配了这么多内存,而不是如何使代码更好。这篇文章可能会有所帮助,这并不能解释为什么int*指针=(int*)calloc(1,sizeof(int));分配0x21000字节
new
并不一定比
calloc
更好。后者可能会指示操作系统惰性地将初始化内存块归零,而最好的办法是访问所有内存并立即将其归零,从而导致一系列页面错误。
(gdb) !getconf PAGE_SIZE
4096
int* pointer = new int(1);