segmentation fault when calling brk() and printf()

74 Views Asked by At

Note: sys_brk returns the program break while brk() returns 0 or -1.(According to manual brk(2), NOTES)

The following code can pass.

#include <unistd.h>
#include <stdio.h>
#include <sys/syscall.h>
#include <string.h>
#include <stdint.h>

int main (void)
{
    long beg_break = syscall (SYS_brk, 0);//get current program break.
    
    long mid_break =  syscall (SYS_brk, beg_break + 100);
    
    long end_break = syscall (SYS_brk, beg_break);//set the program break back
}

But there will be a segmentation fault at the line syscall (SYS_brk, beg_break) if I try to print them:

( My question is at the end.)

long beg_break = syscall (SYS_brk, 0);
printf ("%#lX\n", beg_break);

long mid_break =  syscall (SYS_brk, beg_break + 100);
printf ("%#lX\n", mid_break);

long end_break = syscall (SYS_brk, beg_break);
printf ("%#lX\n", end_break);

Output:

0X557E46CDE000
0X557E46CDE064
Segementation fault

It's not accendital, I have tried many times on different PCs, also the experiments below:

  1. using stderr instead of stdout, it works.
long beg_break = syscall (SYS_brk, 0);
fprintf (stderr, "%#lX\n", beg_break);

long new_break =  syscall (SYS_brk, beg_break + 100);
fprintf (stderr, "%#lX\n", new_break);

long end_break = syscall (SYS_brk, beg_break);
fprintf (stderr, "%#lX\n", end_break);
  1. not using printf() between brk(), it works.
long beg_break = syscall (SYS_brk, 0);
long mid_break =  syscall (SYS_brk, beg_break + 100);
long end_break = syscall (SYS_brk, beg_break);

printf ("%#lX\n", beg_break);
printf ("%#lX\n", mid_break);
printf ("%#lX\n", end_break);
  1. disable buffering of stdout, it works.
setvbuf (stdout, NULL, _IONBF, 0);
long beg_break = syscall (SYS_brk, 0);
printf ("%#lX\n", beg_break);

long mid_break =  syscall (SYS_brk, beg_break + 100);
printf ("%#lX\n", mid_break);

long end_break = syscall (SYS_brk, beg_break);
printf ("%#lX\n", end_break);

So I guess it results from printf() calling malloc(), which bases on brk():

long beg = syscall (SYS_brk, 0);
printf ("hello world %d\n", 123);
long end = syscall (SYS_brk, 0);

printf ("%#lX\n", beg);
printf ("%#lX\n", end);

The output:

hello world 123
0X56501B6F0000
0X56501B711000

It seems that I should avoid using C library with brk():

Since brk() doesn't write/read the memory on heap, why brk(), instead of printf(), results in the segmentation fault ?

0

There are 0 best solutions below