代码之家  ›  专栏  ›  技术社区  ›  St.Antario

在C中理解printf

  •  8
  • St.Antario  · 技术社区  · 7 年前

    printf 在C中用于一个简单的情况。我写了以下程序:

    #include "stdio.h"
    
    int main(int argc, char const *argv[])
    {
        printf("Test %s\n", argv[1]);
        return 0;
    }
    

    跑步 objdump 在二进制文件上我注意到 Test %s\n .rodata

    objdump -sj .rodata bin
    
    bin:     file format elf64-x86-64
    
    Contents of section .rodata:
     08e0 01000200 54657374 2025730a 00        ....Test %s..
    

    所以格式化打印似乎执行额外的模式复制 rodata 去别的地方。

    编译并运行之后 stare ./bin rr 我注意到一个 brk 在实际写入之前进行syscall。所以用它来运行

    gdb catch syscall brk
    gdb catch syscall write
    

    显示在我的例子中,当前的中断等于 0x555555756000 ,但它随后设置为 0x555555777000 . 当 write

    x/s $rsi
    0x555555756260: "Test rr\n"
    

    介于“旧”和“新”之间。写入发生后,程序退出。

    问题: 刹车 而不是 mmap 这样的格式?

    2 回复  |  直到 7 年前
        1
  •  1
  •   Ctx    7 年前

    brk() (它是同伴 sbrk() )是某种 mmap() mmap() mremap() 直接。

    malloc() ,这在libc内部发生,例如,有足够的空间从格式字符串和参数或许多其他内部事物(即,在f*函数族中使用缓冲io时的输出缓冲区)创建实际字符串。

        2
  •  1
  •   Jean-Baptiste Yunès    7 年前

    我们为什么要分配这么多页面?

    使用系统调用的成本很高,所以库要求的比您现在想要的更多,因为您很可能很快就会想要更多。以用户模式管理内存成本较低。这是一个粒度问题。

    为什么休息时间没有恢复 写系统调用发生后的前一个?

    再说一次,如果你很快会要求更多的可能性很高,为什么要免费呢?

    有什么理由使用 brk 而不是 mmap 这样的格式?

    这是一个选择的问题,这取决于执行情况。