Malloc behavior (0)

int main() { char *p; p = (char* ) malloc(sizeof(char) * 0); printf("Hello Enter the data without spaces :\n"); scanf("%s",p); printf("The entered string is %s\n",p); //puts(p); } 

When compiling the above code and running it, the program can read a line, even if we assigned 0-byte memory to pointer p.

What actually happens in the p = (char* ) malloc(0) statement?

+8
c pointers
May 21 '12 at 11:42
source share
3 answers

The implementation that malloc() returns is defined, but this behavior is undefined to use this pointer. And undefined behavior means that everything can happen literally from a program that works without failures in the event of a failure, all safe bets are disabled.

C99 Standard:

7.22.3 Memory Management Functions
Paragraph 1:

If the size of the requested space is zero, the behavior is determined by the implementation: a null pointer is returned or the behavior is as if the size were some non-zero value, except that the returned pointer should not be used to access the object.

+12
May 21 '12 at 11:43
source share

In addition to Als comment - what happens: you write somewhere in memory and retrieve data from there. Therefore, depending on your system and OS type, you get an exception or just undefined behavior

0
May 21 '12 at 12:29
source share

Just out of curiosity, I tested your code with gcc on linux, and it is much more reliable than I would have expected (after all, writing data to a character buffer of length 0 is undefined behavior). I would expect it to crash).

Here is my modification of your code:

 #include <stdio.h> #include <stdlib.h> int main() { char *p; p = malloc(sizeof(char)*0); printf("Hello Enter some without spaces :\n"); scanf("%s",p); char *q; q = malloc(sizeof(char)*0); printf("Hello Enter more data without spaces :\n"); scanf("%s",q); printf("The first string is '%s'\n",p); printf("The second string is '%s'\n",q); } 

My first thought was that you can be saved by the fact that you only read data in one memory location - if you use two buffers, the second can overwrite the first ... so I broke the code in the input and output section:

 Hello Enter some without spaces : asdf Hello Enter more data without spaces : tutututu The first string is 'asdf' The second string is 'tutututu' 

If the first buffer has been overwritten, we will see

 The first string is 'tutututu' The second string is 'tutututu' 

So that is not the case. [but it depends on how much data you are packing into each buffer ... see below]

Then I entered a crazy amount of data into both variables:

 perl -e 'print "c" x 5000000 . "\n" ' | xsel -i 

(This puts 4+ MB 'c in the copy buffer). I inserted this in the first and second scanf calls. The program took it without segmentation error.

Despite the fact that I did not have a segmentation error, the first buffer was overwritten. I could not say this because so much data appeared on the screen. Here's the mileage with less data:

 $ ./foo Hello Enter some without spaces : aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Hello Enter more data without spaces : ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc The first string is 'aaaaaaaaaaaa' The second string is '' 

After aaaaaaaaaaaaa, a small glyph appeared, which, like my terminal, represents a unicode character that it cannot display. This is typical of overwritten data: you do not know what will overwrite your data ... this behavior is undefined, so you are prone to nasal daemons.

The bottom line is that when you write in memory that you have not allocated space for (either explicitly using malloc or implicitly with an array), you play with fire. Sooner or later, you will overwrite the memory and cause yourself all kinds of grief.

The real lesson here is that C does not perform bounds checking. He will gladly allow you to write in your memory what you do not have. You can do it all day. Your program may work correctly, or maybe not. This may cause a crash, it may write corrupted data, or it may work until you scan another byte than you used during testing. It doesn’t matter, so you need to.

The case of malloc(0) is just a special case of this question .

0
May 21 '12 at 1:35 pm
source share



All Articles