【问题标题】:Initial size of heap memory for a program程序堆内存的初始大小
【发布时间】:2015-07-06 12:52:38
【问题描述】:

程序:

#include<stdio.h>
#include<sys/types.h>
#include<malloc.h>
main()
{
    int *i1, *i2;
    char *s;
    printf("sbrk(0) before malloc(4): %x\n", sbrk(0));
    i1 = (int *) malloc(sizeof(int));
    printf("sbrk(0) after `i1 = (int *) malloc(4)': %x\n", sbrk(0));
    i2 = (int *) malloc(sizeof(int));
    printf("sbrk(0) after `i2 = (int *) malloc(4)': %x\n", sbrk(0));
}

输出:

sbrk(0) before malloc(4): a027000
sbrk(0) after `i1 = (int *) malloc(4)': a048000
sbrk(0) after `i2 = (int *) malloc(4)': a048000

上述程序的堆内存的初始大小是多少。我认为,在程序的初始阶段, 堆是一样的。有一次,我们调用 malloc,它使用 sbrk 分配内存。

上面的程序表明,首先 sbrk(0) 返回 a027000 作为程序中断。 malloc 语句执行后,更改程序断点 到a048000。它表明,在调用 malloc 之前,堆没有 足够的内存。因此,调用 malloc 后只更改程序中断。在 初始状态,如果堆有足够的内存,则无需更改 程序中断。所以起初,堆的大小为零。对吗?

【问题讨论】:

  • 一个好的答案取决于架构 - 请告诉我们您的操作系统和硬件。根据您的操作系统,您可能有某种跟踪工具 - 您可以在跟踪下运行您的程序。您可能会在启动过程中看到对 brk() 系列系统调用的调用。 malloc 在某些系统上使用堆分箱 - 这意味着它有自己的堆块,与 libc 分开。
  • 您的printf()-说明符错误。 %x 需要 unsigned int 类型的参数,而 sbrk() 返回 void *
  • 您还需要定义何时测量“初始”尺寸。在调用main() 之前可以运行相当多的代码。
  • 我正在使用“Linux ltsp63 3.2.0-33-generic #52-Ubuntu SMP Thu Oct 18 16:19:45 UTC 2012 i686 i686 i386 GNU/Linux”

标签: c linux unix


【解决方案1】:

会发生什么取决于您的操作系统在调用 main() 之前所做的工作。

在 Mac OS X 上,在调用 main() 函数之前会分配大量内存。我目前有一个大约 18 个被抑制的“内存滥用”的列表,这些都来自系统提供的启动代码调用 main() 之前发生的事情。

运行一个简单的程序,每行打印一个参数,但不给它任何参数,因此没有输出,从valgrind 生成一个使用报告,如下所示:

==59405== Memcheck, a memory error detector
==59405== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==59405== Using Valgrind-3.11.0.SVN and LibVEX; rerun with -h for copyright info
==59405== Command: /Users/jleffler/bin/al
==59405== 
--59405-- /Users/jleffler/bin/al:
--59405-- dSYM directory is missing; consider using --dsymutil=yes
--59405-- UNKNOWN mach_msg unhandled MACH_SEND_TRAILER option
--59405-- UNKNOWN mach_msg unhandled MACH_SEND_TRAILER option (repeated 2 times)
--59405-- UNKNOWN mach_msg unhandled MACH_SEND_TRAILER option (repeated 4 times)
==59405== 
==59405== HEAP SUMMARY:
==59405==     in use at exit: 34,808 bytes in 417 blocks
==59405==   total heap usage: 517 allocs, 100 frees, 41,784 bytes allocated
==59405== 
==59405== LEAK SUMMARY:
==59405==    definitely lost: 16 bytes in 1 blocks
==59405==    indirectly lost: 0 bytes in 0 blocks
==59405==      possibly lost: 13,002 bytes in 109 blocks
==59405==    still reachable: 21,790 bytes in 307 blocks
==59405==         suppressed: 0 bytes in 0 blocks
==59405== Rerun with --leak-check=full to see details of leaked memory
==59405== 
==59405== For counts of detected and suppressed errors, rerun with: -v
==59405== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

程序的代码?

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)  
{ 
    if (argc > 1)
    {
        while (*++argv) 
            puts(*argv);
    }
    return(EXIT_SUCCESS); 
}

很多内存活动,但在我编写的代码中没有。泄漏是我在抑制文件中记录的众多数字之一。

【讨论】:

    【解决方案2】:

    安装 glibc debuginfo 后(例如在 Fedora 22 上:dnf debuginfo-install glibc-2.21-5.fc22.x86_64),可以打印出 main_arenamp_

    使用空的int main(void) 调试程序:

    mp_.sbrk_base 是堆的基数。在我的 Linux 上,main 被称为堆不存在。调用malloc(1000)mp_.sbrk_base0x602000main_arena.top 是堆顶的空闲内存块。是0x6023f0

    (gdb) b main
    Breakpoint 1 at 0x4004fa: file test.c, line 3.
    (gdb) r 
    Starting program: /home/m/a.out 
    
    Breakpoint 1, main () at test.c:3
    3       return 0;
    (gdb) p mp_
    $1 = {trim_threshold = 131072, top_pad = 131072, mmap_threshold = 131072, arena_test = 8, arena_max = 0, n_mmaps = 0, 
      n_mmaps_max = 65536, max_n_mmaps = 0, no_dyn_threshold = 0, mmapped_mem = 0, max_mmapped_mem = 0, max_total_mem = 0, 
      sbrk_base = 0x0}
    (gdb) p main_arena 
    $2 = {mutex = 0, flags = 0, fastbinsY = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, top = 0x0, 
      last_remainder = 0x0, bins = {0x0 <repeats 254 times>}, binmap = {0, 0, 0, 0}, next = 0x7ffff7dd6b20 <main_arena>, 
      next_free = 0x0, system_mem = 0, max_system_mem = 0}
    (gdb) call malloc(1000)
    $3 = (void *) 0x602010
    (gdb) p mp_
    $4 = {trim_threshold = 131072, top_pad = 131072, mmap_threshold = 131072, arena_test = 8, arena_max = 0, n_mmaps = 0, 
      n_mmaps_max = 65536, max_n_mmaps = 0, no_dyn_threshold = 0, mmapped_mem = 0, max_mmapped_mem = 0, max_total_mem = 0, 
      sbrk_base = 0x602000 ""}
        (gdb) p main_arena
    $5 = {mutex = 0, flags = 1, fastbinsY = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, top = 0x6023f0, 
      last_remainder = 0x0, bins = {0x7ffff7dd6b78 <main_arena+88>, 0x7ffff7dd6b78 <main_arena+88>, [...]
    0x7ffff7dd7198 <main_arena+1656>, 0x7ffff7dd71a8 <main_arena+1672>, 0x7ffff7dd71a8 <main_arena+1672>...}, binmap = {0, 
    0, 0, 0}, next = 0x7ffff7dd6b20 <main_arena>, next_free = 0x0, system_mem = 135168, max_system_mem = 135168}
    
    (gdb) call sbrk(0)
    $6 = 6434816
    (gdb) p (void*)$6
    $7 = (void *) 0x623000
    (gdb) 
    

    【讨论】:

      猜你喜欢
      • 2010-10-28
      • 2010-12-29
      • 1970-01-01
      • 2018-04-14
      • 2013-11-12
      • 1970-01-01
      • 1970-01-01
      • 2012-09-19
      • 2020-02-13
      相关资源
      最近更新 更多