1
#include <stdio.h>

void wat(void *ptr){
    *(int*)ptr = 0x4A424F4B;
    return;
}

int main(int argc, char **argv){
    FILE *wtf = fopen("wat", "wb");
    void *ptr;
    wat(ptr);
    return 0;
} 

This actually compiles and executes without errors, you can even fwrite contents of *(int*)ptr and you'll get 0x4A424F4B. However, when you remove this line:

FILE *wtf = fopen("wat", "wb");

*(int*)ptr = 0x4A424F4B; will suddenly cause a segmentation fault. Why?

n0p
  • 3,399
  • 2
  • 29
  • 50
m132
  • 269
  • 2
  • 12
  • 1
    This program will cause a undefined behavior. Until unless you pass a valid address to function wat, you cant expect the correct result – mahendiran.b Aug 11 '14 at 05:56
  • http://stackoverflow.com/questions/2397984/undefined-unspecified-and-implementation-defined-behavior – Lundin Aug 11 '14 at 06:19

4 Answers4

6

Technically, your code has undefined behaviour.

It happens to not blow up on your particular platform using your particular compiler because the uninitialized ptr happens to contain the address of some writable memory. Since we don't know where ptr is pointing, we can't know what harm the assignment is doing.

Moving things around changes the addresses, and things "break" (strictly speaking, they weren't really working in the first place).

NPE
  • 486,780
  • 108
  • 951
  • 1,012
3

It's undefined behavior, so anything could happen.

Probably what happened is, with this line

FILE *wtf = fopen("wat", "wb");

A valid pointer value is left in the stack. Then the uninitialized ptr gets it. But again, undefined behavior, you shouldn't rely on it.

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
2
*(int*)ptr = 0x4A424F4B;

means write the integer value 0x4A424F4B into the address that the integer pointer ptr points to. Since you are not initializing the ptr, its behaviour is not defined. The fact the it works in some cases is therefore irrelevant.

perreal
  • 94,503
  • 21
  • 155
  • 181
1

It compiles, but you do get warnings:

$ gcc -Wall -o ptr ptr.c
ptr.c: In function ‘main’:
ptr.c:9:11: warning: unused variable ‘wtf’ [-Wunused-variable]
     FILE *wtf = fopen("wat", "wb");
           ^
ptr.c:11:5: warning: ‘ptr’ is used uninitialized in this function [-Wuninitialized]
     wat(ptr);
     ^

And if you enable the address sanitizer, it will not execute without errors:

$ gcc -fsanitize=address -o ptr ptr.c
$ ./ptr
=================================================================
==3280==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc     0x00000040080d sp 0x7ffffa1f4940 bp 0x7ffffa1f4950 T0)
    #0 0x40080c in wat (/tmp/ptr+0x40080c)
    #1 0x400843 in main (/tmp/ptr+0x400843)
    #2 0x7fa048110b44 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b44)
    #3 0x4006f8 (/tmp/ptr+0x4006f8)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV ??:0 wat
==3280==ABORTING

But yeah, C by default does not come with safety.

pdw
  • 8,359
  • 2
  • 29
  • 41
  • I didn't get any warning, are you using `-Wall`? – m132 Aug 11 '14 at 06:12
  • @M132 I show the commands I use :) Yes, I use -Wall. C compilers usually don't give warnings unless you ask for them. – pdw Aug 11 '14 at 06:14
  • @M132 and on a real projects I actually tend to use `-Wall -Wextra -Wconversion` – pdw Aug 11 '14 at 06:15