9
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);
}

On compiling the above code and running it , the program is able to read the string even though we assigned a 0 byte memory to the pointer p .

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

Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
svKris
  • 783
  • 1
  • 7
  • 21
  • 5
    Off topic.. But it is not a good practice to cast malloc return.. See [this](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) – Krishnabhadra May 21 '12 at 11:45
  • 4
    C doesn't protect you against over-running the buffers you have been assigned - you need to be careful to not do this else you'll trample on someone else's memory. – Rup May 21 '12 at 11:45
  • 1
    possible duplicate of [Why does malloc(0) return a non-null address in Windows?](http://stackoverflow.com/questions/9723030/why-does-malloc0-return-a-non-null-address-in-windows) – Jay May 21 '12 at 12:27

3 Answers3

13

It is implementation defined what malloc() will return but it is undefined behavior to use that pointer. And Undefined behavior means that anything can happen literally from program working without glitch to a crash, all safe bets are off.

C99 Standard:

7.22.3 Memory management functions
Para 1:

If the size of the space requested is zero, the behavior is implementation-defined: either a null pointer is returned, or the behavior is as if the size were some nonzero value, except that the returned pointer shall not be used to access an object.

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

In addition to Als comment - what happens: you write somewhere into memory and retrieve the data from there. So depending of your system and OS type you get a exception or just some undefined behaviour

michelmm
  • 48
  • 5
0

Just out of curiosity, I tested your code using gcc on linux, and its a lot more robust than I would expect (after all, writing data to a character buffer of length 0 is undefined behavior... I would expect it to crash).

Here's 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 might be saved by the fact that you're only reading data into a single memory location -- if you use two buffers, the second might overwrite the first... so I broke the code into input and output sections:

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 had been overwritten, we would see

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

So that's not the case. [but this depends on how much data you pack into each buffer... see below]

Then, I pasted a crazy amount of data into both variables:

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

(This put 4+ MB of 'c's into the copy buffer). I pasted this in to both the first and second scanf calls. The program took it without a segmentation fault.

Even though I didn't have a segmentation fault, the first buffer did get overwritten. I couldn't tell it because so much data went flying up the screen. Here's a run 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 'ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc'

There was a little glyph after aaaaaaaaaaaa, which is how my terminal represents a unicode character that it can't display. This is typical of overwritten data: you don't know what is going to overwrite your data... it's undefined behavior, so you're prone to nasal demons.

The bottom line is that when you write to memory that you haven't allocated space for (either explicitly using malloc or implicitly with an array), you're playing with fire. Sooner or later, you'll overwrite memory and cause yourself all sorts of grief.

The real lesson here is that C doesn't do bounds checking. It will happily let you write to memory that you don't own. You can do it all day long. Your program may run correctly, and it may not. It may crash, it may write back corrupted data, or it might work until you scan in one more byte than you used while testing. It doesn't care, so you have to.

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

Community
  • 1
  • 1
Barton Chittenden
  • 4,238
  • 2
  • 27
  • 46
  • When we are not assigning any memory to the pointer , in such a case writing into a non existent memory should cause a Segmentation fault right? i am working with gcc on linux as well and Segmentation fault is not occurring. I am confused with this behavior of the malloc(0) ! – svKris May 21 '12 at 14:44
  • @svKris My best guess is that when you run malloc(0), you get a pointer somewhere in the heap. malloc doesn't reserve any memory, so you don't have any guarantees that you won't overwrite data elsewhere in the heap, but it (probably) won't seg fault on you. If you try to write to an uninitialized pointer, you're going to be writing to who-knows-what memory address, so you probably will seg fault. Exaxtly how this is handled is implementation dependent. – Barton Chittenden May 21 '12 at 22:29
  • @svKris according to the c99 standard quoted above, malloc(0) may return null, or it may return something else. Writing to a null pointer will give you a seg fault, so apparently that's not what gcc does. – Barton Chittenden May 21 '12 at 22:40
  • 1
    Seriously, there should be **no expectation that it should crash**. It is not defined that it should crash. On the contrary. – Antti Haapala -- Слава Україні Apr 13 '16 at 08:50
  • @BartonChittenden writing to `NULL` "will segfault" is also a wrong assumption. It has undefined behaviour, it is not defined that it has to crash. – Antti Haapala -- Слава Україні Apr 13 '16 at 11:54