Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Writing to pointer out of bounds after malloc() not causing error

when I try the code below it works fine. Am I missing something?

main()
{
    int *p;
    p=malloc(sizeof(int));
    printf("size of p=%d\n",sizeof(p));
    p[500]=999999;
    printf("p[0]=%d",p[500]);
    return 0;
}

I tried it with malloc(0*sizeof(int)) or anything but it works just fine. The program only crashes when I don't use malloc at all. So even if I allocate 0 memory for the array p, it still stores values properly. So why am I even bothering with malloc then?

like image 992
marr Avatar asked Dec 26 '10 17:12

marr


People also ask

What causes malloc error?

The most likely causes are writing outside the bounds of an allocated object, or writing to an object after it has been deleted. These errors can be difficult to track down with a debugger.

What happens if malloc is not freed?

If free() is not used in a program the memory allocated using malloc() will be de-allocated after completion of the execution of the program (included program execution time is relatively small and the program ends normally).

What happens if malloc Cannot allocate memory?

If the malloc function is unable to allocate the memory buffer, it returns NULL. Any normal program should check the pointers which the malloc function returns and properly handle the situation when the memory allocation failed.

What does function malloc () return on error?

malloc returns a void pointer to the allocated space, or NULL if there is insufficient memory available.


6 Answers

It might appear to work fine, but it isn't very safe at all. By writing data outside the allocated block of memory you are overwriting some data you shouldn't. This is one of the greatest causes of segfaults and other memory errors, and what you're observing with it appearing to work in this short program is what makes it so difficult to hunt down the root cause.

Read this article, in particular the part on memory corruption, to begin understanding the problem.

Valgrind is an excellent tool for analysing memory errors such as the one you provide.

@David made a good comment. Compare the results of running your code to running the following code. Note the latter results in a runtime error (with pretty much no useful output!) on ideone.com (click on links), whereas the former succeeds as you experienced.

int main(void)
{
    int *p;
    p=malloc(sizeof(int));
    printf("size of p=%d\n",sizeof(p));
    p[500]=999999;
    printf("p[0]=%d",p[500]);
    p[500000]=42;
    printf("p[0]=%d",p[500000]);
    return 0;
}
like image 120
moinudin Avatar answered Oct 23 '22 15:10

moinudin


If you don't allocate memory, p has garbage in it, so writing to it likely will fail. Once you made a valid malloc call, p is pointing to valid memory location and you can write to it. You are overwriting memory that you shouldn't write to, but nobody's going to hold your hand and tell you about it. If you run your program and a memory debugger such as valgrind, it will tell you. Welcome to C.

like image 44
MK. Avatar answered Oct 23 '22 14:10

MK.


Writing past the end of your memory is Undefined Behaviour™, which means that anything could happen- including your program operating as if what you just did was perfectly legal. The reason for your program running as if you had done malloc(501*sizeof(int)) are completely implementation-specific, and can indeed be specific to anything, including the phase of the moon.

like image 28
Puppy Avatar answered Oct 23 '22 13:10

Puppy


This is because P would be assigned some address no matter what size you use with malloc(). Although, with a zero size you would be referencing invalid memory as the memory hasn't been allocated, but it may be within a location which wouldn't cause program crash, though the behavior will be undefined.

Now if you do not use malloc(), it would be pointing to a garbaging location and trying to access that is likely to cause program crash.

like image 41
Shamim Hafiz - MSFT Avatar answered Oct 23 '22 15:10

Shamim Hafiz - MSFT


I tried it with malloc(0*sizeof(int))

According to C99 if the size passed to malloc is 0, a C runtime can return either a NULL pointer or the allocation behaves as if the request was for non-zero allocation, except that the returned pointer should not be dereferenced. So it is implementation defined (e.g. some implementations return a zero-length buffer) and in your case you do not get a NULL pointer back, but you are using a pointer you should not be using.If you try it in a different runtime you could get a NULL pointer back.

like image 20
Cratylus Avatar answered Oct 23 '22 13:10

Cratylus


When you call malloc() a small chunk of memory is carved out of a larger page for you.

    malloc(sizeof(int));

Does not actually allocate 4 bytes on a 32bit machine (the allocator pads it up to a minimum size) + size of heap meta data used to track the chunk through its lifetime (chunks are placed in bins based on their size and marked in-use or free by the allocator). hxxp://en.wikipedia.org/wiki/Malloc or more specifically hxxp://en.wikipedia.org/wiki/Malloc#dlmalloc_and_its_derivatives if you're testing this on Linux.

So writing beyond the bounds of your chunk doesn't necessarily mean you are going to crash. At p+5000 you are not writing outside the bounds of the page allocated for that initial chunk so you are technically writing to a valid mapped address. Welcome to memory corruption. http://www.google.com/search?sourceid=chrome&ie=UTF-8&q=heap+overflows

like image 44
ChrisRohlf Avatar answered Oct 23 '22 14:10

ChrisRohlf