为什么打印会导致堆中断增加这么多?

问题描述 投票:0回答:1

我写了以下程序,

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include "rand.h"

int main (int argc, char* argv[]) {

  void *x = sbrk(0);
  printf("The initial top of the heap is %p.\n", x);
  void *y = sbrk(0);
  printf("The current top of the heap is %p.\n", y);
  printf("The difference is %d (%x)\n", (int) (y-x), (int) (y-x));
  return 0;
}

我明白为什么堆中断不同,因为它必须为打印调用分配堆空间。

我不明白的是为什么在我的 x86_64 Linux 计算机上,差异具体是 25600 字节。

就像,字符串本身可能只需要少量字节(每个字节一个字符,向堆中的字符串添加一些头数据),甚至不需要 1000 个字节,对吗?

我有一点猜测,这可能与分页有关——我还不太明白。 但从简单的搜索来看,似乎分页一次只分配大约 4000 字节,所以可能也不是这样,对吧?

也许各种

include
与此有关? 老实说,我根本不知道这会如何影响堆内存。


不管怎样,直接的问题是:为什么这个程序会导致堆内存移动25600字节?

c heap-memory sbrk
1个回答
0
投票

为什么打印会导致堆中断增加这么多?

因为“打印”分配内存,所以移动堆中断。在调试器下运行程序,您可能会观察到:

(gdb) bt
#0  __GI___sbrk (increment=increment@entry=135168) at sbrk.c:37
#1  0x00007ffff7e45b36 in __glibc_morecore (increment=increment@entry=135168) at /usr/src/debug/glibc/glibc/malloc/morecore.c:29
#2  0x00007ffff7e46bfd in sysmalloc (nb=nb@entry=656, av=av@entry=0x7ffff7f87ac0 <main_arena>) at malloc.c:2709
#3  0x00007ffff7e47c5a in _int_malloc (av=av@entry=0x7ffff7f87ac0 <main_arena>, bytes=bytes@entry=640) at malloc.c:4481
#4  0x00007ffff7e47f37 in tcache_init () at malloc.c:3252
#5  0x00007ffff7e48776 in tcache_init () at malloc.c:3248
#6  __GI___libc_malloc (bytes=bytes@entry=1024) at malloc.c:3313
#7  0x00007ffff7e21f14 in __GI__IO_file_doallocate (fp=0x7ffff7f885c0 <_IO_2_1_stdout_>) at filedoalloc.c:101
#8  0x00007ffff7e31214 in __GI__IO_doallocbuf (fp=0x7ffff7f885c0 <_IO_2_1_stdout_>) at /usr/src/debug/glibc/glibc/libio/libioP.h:1030
#9  __GI__IO_doallocbuf (fp=fp@entry=0x7ffff7f885c0 <_IO_2_1_stdout_>) at genops.c:342
#10 0x00007ffff7e2f2e8 in _IO_new_file_overflow (f=0x7ffff7f885c0 <_IO_2_1_stdout_>, ch=-1) at fileops.c:745
#11 0x00007ffff7e2fde8 in _IO_new_file_xsputn (f=0x7ffff7f885c0 <_IO_2_1_stdout_>, data=<optimized out>, n=47)
    at /usr/src/debug/glibc/glibc/libio/libioP.h:1030
#12 _IO_new_file_xsputn (f=0x7ffff7f885c0 <_IO_2_1_stdout_>, data=<optimized out>, n=47) at fileops.c:1197
#13 0x00007ffff7dfd549 in __printf_buffer_flush_to_file (buf=buf@entry=0x7fffffffd9b0) at ../libio/libioP.h:1030
#14 0x00007ffff7dfd60c in __printf_buffer_to_file_done (buf=buf@entry=0x7fffffffd9b0) at printf_buffer_to_file.c:120
#15 0x00007ffff7e08e0c in __vfprintf_internal (s=0x7ffff7f885c0 <_IO_2_1_stdout_>, 
    format=0x555555556008 "The initial top of the heap is %p.\n", ap=ap@entry=0x7fffffffdab0, mode_flags=mode_flags@entry=0)
    at vfprintf-internal.c:1545
#16 0x00007ffff7dfccf3 in __printf (format=<optimized out>) at printf.c:33
#17 0x0000555555555181 in main ()

分配来自 glibc 为 stdout 分配缓冲区 https://github.com/lattera/glibc/blob/master/libio/fileops.c#L752 .

© www.soinside.com 2019 - 2024. All rights reserved.