Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Execution of printf() and Segmentation Fault

#include<stdio.h>  int main() {     char *name = "Vikram";     printf("%s",name);     name[1]='s';     printf("%s",name);     return 0; } 

There is no output printed on terminal and just get segmentation fault. But when I run it in GDB, I get following -

Program received signal SIGSEGV, Segmentation fault. 0x0000000000400525 in main () at seg2.c:7 7       name[1]='s'; (gdb)  

This means program receive SEG fault on 7th line (obviously I can't write on constant char array) . Then why printf() of line number 6 is not executed ?

like image 751
Vikram Avatar asked Feb 27 '12 17:02

Vikram


People also ask

What happens when a segmentation fault occurs?

A segmentation fault occurs when a program attempts to access a memory location that it is not allowed to access, or attempts to access a memory location in a way that is not allowed (for example, attempting to write to a read-only location, or to overwrite part of the operating system).

How can segmentation fault be resolved?

It can be resolved by having a base condition to return from the recursive function. A pointer must point to valid memory before accessing it.

What is segmentation fault in C with example?

A segmentation fault occurs when your program attempts to access an area of memory that it is not allowed to access. In other words, when your program tries to access memory that is beyond the limits that the operating system allocated for your program.


2 Answers

This is due to stream buffering of stdout. Unless you do fflush(stdout) or you print a newline "\n" the output is may be buffered.

In this case, it's segfaulting before the buffer is flushed and printed.

You can try this instead:

printf("%s",name); fflush(stdout);        //  Flush the stream. name[1]='s';           //  Segfault here (undefined behavior) 

or:

printf("%s\n",name);   //  Flush the stream with '\n' name[1]='s';           //  Segfault here (undefined behavior) 
like image 75
Mysticial Avatar answered Oct 09 '22 16:10

Mysticial


First you should end your printfs with "\n" (or at least the last one). But that is not related to the segfault.

When the compiler compiles your code, it splits the binary into several section. Some are read only, while other are writeable. Writing to an read only section may cause a segfault. String literals are usually placed in a read only section (gcc should put it in ".rodata"). The pointer name points to that ro section. Therefore you must use

const char *name = "Vikram"; 

In my response I've used a few "may" "should". The behaviour depends on your OS, compiler and compilation settings (The linker script defines the sections).

Adding

-Wa,-ahlms=myfile.lst 

to gcc's command line produces a file called myfile.lst with the generated assembler code. At the top you can see

    .section .rodata .LC0:     .string "Vikram" 

Which shows that the string is in Vikram.

The same code using (Must be in global scope, else gcc may store it on the stack, notice it is an array and not a pointer)

char name[] = "Vikram"; 

produces

    .data     .type name, @object     .size name, 7 name:     .string "Vikram" 

The syntax is a bit different but see how it is in .data section now, which is read-write. By the way this example works.

like image 35
paul Avatar answered Oct 09 '22 18:10

paul