behaviour of malloc(0)

后端 未结 3 2056
旧巷少年郎
旧巷少年郎 2020-11-30 13:48
int main()
{
    char *p;
    p = (char* ) malloc(sizeof(char) * 0);
    printf(\"Hello Enter the data without spaces :\\n\");
    scanf(\"%s\",p);
    printf(\"The          


        
相关标签:
3条回答
  • 2020-11-30 14:35

    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.

    0 讨论(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.

    0 讨论(0)
  • 2020-11-30 14:47

    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

    0 讨论(0)
提交回复
热议问题