Valgrind:stdio.h的函数"puts"分配内存

Eri*_*k W 4 c valgrind

我只是注意到valgrind显示此代码分配内存:

#include <stdio.h>

int main(void)
{
    puts("Hello world");
}
Run Code Online (Sandbox Code Playgroud)

编译时的结果gcc (Ubuntu 5.3.1-14ubuntu2.1):

==25080== Memcheck, a memory error detector
==25080== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==25080== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==25080== Command: ./a.out
==25080== 
Hello world
==25080== 
==25080== HEAP SUMMARY:
==25080==     in use at exit: 0 bytes in 0 blocks
==25080==   total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated
==25080== 
==25080== All heap blocks were freed -- no leaks are possible
==25080== 
==25080== For counts of detected and suppressed errors, rerun with: -v
==25080== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Run Code Online (Sandbox Code Playgroud)

为什么它显示puts分配内存?

zwo*_*wol 8

GNU C库("glibc",Ubuntu上常用的C运行时)为内部使用分配内存,第一次stdout用于任何事情.(对于stderr和它可能也是一样的stdin.)为了看到这种情况,运行你的程序gdb,在它到达之后main,设置断点brkmmap,这是最终用于分配内存的系统调用.然后继续.

Reading symbols from ./a.out...done.
(gdb) b main
Breakpoint 1 at 0x4004ea: file test.c, line 5.
(gdb) r
Starting program: /home/zack/a.out 

Breakpoint 1, main () at test.c:5
5     puts("Hello world");
(gdb) b brk
Breakpoint 2 at 0x7ffff7b183c0: file ../sysdeps/unix/sysv/linux/x86_64/brk.c, line 31.
(gdb) b mmap
Breakpoint 3 at 0x7ffff7b1bc00: file ../sysdeps/unix/syscall-template.S, line 84.
(gdb) c
Continuing.

Breakpoint 3, mmap64 () at ../sysdeps/unix/syscall-template.S:84
84  ../sysdeps/unix/syscall-template.S: No such file or directory.
(gdb) bt
#0  mmap64 () at ../sysdeps/unix/syscall-template.S:84
#1  0x00007ffff7a9f49c in __GI__IO_file_doallocate (
    fp=0x7ffff7dd6620 <_IO_2_1_stdout_>) at filedoalloc.c:128
#2  0x00007ffff7aac550 in __GI__IO_doallocbuf (
    fp=fp@entry=0x7ffff7dd6620 <_IO_2_1_stdout_>) at genops.c:418
#3  0x00007ffff7aab9d8 in _IO_new_file_overflow (
    f=0x7ffff7dd6620 <_IO_2_1_stdout_>, ch=-1) at fileops.c:820
#4  0x00007ffff7aaab8a in _IO_new_file_xsputn (
    f=0x7ffff7dd6620 <_IO_2_1_stdout_>, data=0x400584, n=11) at fileops.c:1331
#5  0x00007ffff7aa18d8 in _IO_puts (str=0x400584 "Hello world") at ioputs.c:41
#6  0x00000000004004f4 in main () at test.c:5
Run Code Online (Sandbox Code Playgroud)

你可以看到调用堆栈通过一堆内部的东西,最终到达puts.

也许你想知道为什么图书馆会这样做.原因在Chuck Walbourn的回答中暗示:内存将用于缓冲输出,并且stdout在第一次使用之前不会分配,因为有些程序从不使用,stdout并且他们不想浪费内存.(这个设计决定可能在20年前更有意义.)