-4

My main.c contents :

int main(int argc, char **argv)  
{  
    void * tmp = malloc(8);  
    ((double *)tmp)[0] = 100;  
    ((double *)tmp)[1] = 102;  
    printf("tmp %p\n", tmp);  
    printf("tmp[0] %d %f %p\n", sizeof(((double *)tmp)[0]), ((double *)tmp)[0], &((double *)tmp)[0]);  
    printf("tmp[1] %d %f %p\n", sizeof(((double *)tmp)[1]), ((double *)tmp)[1], &((double *)tmp)[1]);  
    return EXIT_SUCCESS;  
}  

=========================OUTPUT=========================  
tmp 0xee8010  
tmp[0] 8 100.000000 0xee8010  
tmp[1] 8 102.000000 0xee8018  
========================================================

First, I did allocate 8 bytes of memory in variable tmp and I assigned number 100 to address 0xee8010.

((double *)tmp)[0] = 100;  

I also assign number 102 to unallocated memory 0xee8018.

((double *)tmp)[1] = 102;  

But I didn't see any error message at build-time nor at runtime. Why not?

Please help me understand this. Thank you.

Lundin
  • 195,001
  • 40
  • 254
  • 396

2 Answers2

3

Writing to unallocated or writing beyond bounds of allocated memory results in Undefined Behavior(UB) which does not necessarily warrant a crash.
An Undefined behavior means that any behavior can be observed the compiler implementation does not need to do anything specific(like a segmentation fault as you expect) when an UB occurs.

But I didn't see any error message at the build time and runtime.

You get compile time errors for code which do not abide to the language standard. In this case the code abides to the language standard but does something who's outcome is not defined by the language standard.

Alok Save
  • 202,538
  • 53
  • 430
  • 533
0

A good habit would be to always match your malloc() call with a free(). Another error-prone habit is casting. If the pointer instead was declared as a double you could automagicly get its size right in the malloc() and reduce the risk of accidentally cast a pointer to a variable or vice versa.

There are no runtime warnings of a buffer overrun in c as it was designed to be efficiently mapped to machine code. To catch memory leaks and buffer overruns you could use external tools valgrind http://valgrind.org/ to analyse your code. It will insert extra instructions when you are accessing memory to trap this undefined behaviour.

    int main(int argc, char **argv)
    {
            double *tmp;
            if( tmp = malloc(2*sizeof(tmp)) ){
                    tmp[0]=100;
                    tmp[1]=102;
                    printf("tmp %p\n", tmp);
                    printf("tmp[0] %d %f %p\n", (int)tmp[0], tmp[0], &tmp[0]);
                    printf("tmp[1] %d %f %p\n", (int)tmp[1], tmp[1], &tmp[1]);
                    free(tmp);

                    //return EXIT_SUCCESS;  
                    return(0);
            }else{
                    //Malloc failed
                    return(-1);
            }
    }
Simson
  • 3,373
  • 2
  • 24
  • 38