C Valgrind:stdio.h';“s函数”;把「;分配内存

C Valgrind:stdio.h';“s函数”;把「;分配内存,c,valgrind,C,Valgrind,我刚刚注意到valgrind显示了以下代码分配内存: #include <stdio.h> int main(void) { puts("Hello world"); } 为什么它显示put分配内存 默认情况下,标准允许缓冲标准输出。您可以使用。GNU C库(“glibc”,Ubuntu上常见的C运行时)在stdout第一次用于任何事情时分配内存供内部使用。(对于stderr和stdin可能也会这样做)要看到这种情况,请在gdb下运行程序,并在到达main后,在brk和m

我刚刚注意到valgrind显示了以下代码分配内存:

#include <stdio.h>

int main(void)
{
    puts("Hello world");
}
为什么它显示
put
分配内存

默认情况下,标准允许缓冲标准输出。您可以使用。

GNU C库(“glibc”,Ubuntu上常见的C运行时)在
stdout
第一次用于任何事情时分配内存供内部使用。(对于
stderr
stdin
可能也会这样做)要看到这种情况,请在
gdb
下运行程序,并在到达
main
后,在
brk
mmap
上设置断点,这是最终用于分配内存的系统调用。然后继续

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
从读取符号。/a.out…完成。
(gdb)b干管
0x4004ea处的断点1:文件test.c,第5行。
(gdb)r
启动程序:/home/zack/a.out
test.c处的断点1,main():5
5认沽期权(“你好世界”);
(gdb)b brk
0x7ffff7b183c0处的断点2:file../sysdeps/unix/sysv/linux/x86_64/brk.c,第31行。
(gdb)b mmap
断点3位于0x7ffff7b1bc00:file../sysdeps/unix/syscall template.S,第84行。
(gdb)c
持续的。
断点3,mmap64()位于../sysdeps/unix/syscall template.S:84
84../sysdeps/unix/syscall template.S:没有这样的文件或目录。
(gdb)英国电信
#0 mmap64()位于../sysdeps/unix/syscall template.S:84
#1 0x00007FF7A9F49C,位于GI IO文件中(
fp=0x7ffff7dd6620)位于filedoalloc.c:128
#2 0x00007FF7AAC550英寸(
计划生育=fp@entry=0x7ffff7dd6620)在genops处。c:418
#3 0x00007FF7AAB9D8输入新文件溢出(
f=0x7ffff7dd6620,ch=-1)位于fileops.c:820
#4 0x00007FF7AAAB8A在新文件中(
f=0x7ffff7dd6620,数据=0x400584,n=11)位于fileops.c:1331
#5 0x00007FF7AA18D8输入输出(str=0x400584“Hello world”)在ioputs处。c:41
#测试c:5时主()中的6 0x0000000000404F4
您可以看到,调用堆栈经历了一系列内部内容,最终位于
put


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

我不知道
puts
是否分配内存,但有可能在
stdio.h
中,一些内存最初是出于某种原因分配的,尽管我必须诚实地说,我不知道valgrind如何进行检查。我想对你的问题最好的回答是直接查看
stdio.h
的源代码,尤其是
put
,这通常是可用的。如果删除
put
和include会发生什么?当我测试你的程序时,我得到了0个alloc(使用gcc(Debian 5.3.1-21)),你是否尝试添加了“return 0;”然后运行程序?使用源代码,如果你通过它,你会看到一个缓冲区被传递到文件。虽然这肯定是真的,但我看不出这如何澄清OP的问题。问题是“它为什么分配内存?”。答案是“它缓冲”。40年前的决定更有意义:)此时,标准委员会不愿意更改这些古老的功能,因为担心会破坏数百万(数十亿?)现有的代码。@ChuckWalbourn你没有错,但是,据我所知,这是一个纯粹的QoI问题-一个静态分配stdin/out/err默认缓冲区的实现将同样符合要求,只要
setvbuf
仍然有效。为什么我们不能在回溯中看到“malloc”?我本以为他们会重用自己的胆量,所以他们一定有很好的理由不这样做?@johanneschaub litb事实上,glibc 2.22将此更改为使用malloc而不是mmap:使用mmap的最初原因似乎是“定制malloc实现可能不提供calloc”(参见,引用“1996年12月的讨论”);但零缓冲区似乎不再是一个要求。我的堆栈跟踪是在Debian jessie上生成的,它仍然在2.19上。
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