views:

104

answers:

2

Hi there, a malloc question.

First, I generate some strings.

And second, I allocate none-space for copying pointers which point to those strings. At this moment the program should probably crash, since I ve tried to copy those pointers to nowhere, but it doesn’t crash. How is it possible?

Any comments would be appreciated.

#include <stdio.h>

int main(int argc, char *argv[])
{
    int         i,
                iJ,
                iCharCount  = 0,
                iCharVal,
                iStrLen = 0,
                iStrNum = 50,
                iStrCount = 0,
                iAllocSize = 0;
    char       *pcStr,
               *pcStr_CurPos,
             **ppcStr,
             **ppcStr_CurPos;

    // suppose, an average length of string is * N bytes.
    iAllocSize  = iStrNum * 6;
    iStrCount = 0;

    // allocate ...
    pcStr = pcStr_CurPos = (char*) malloc (iAllocSize);

    if (pcStr==NULL){printf("NULL == malloc()\n"); exit (1);}

    for (i=0; i < iStrNum; i++)
    {
        iStrCount++;
        iStrLen = rand() % 7 + 2; // is in the range 2 to 8
            printf("Len of Str=%d; str=[", iStrLen);
        for (iJ = 0; iJ < iStrLen-1; iJ++)
        {
            // A-Z a-z
            iCharVal = rand() % 58 + 65;

            if (iCharVal >  90 && iCharVal < 97) {iJ--; continue;}

            if (pcStr_CurPos < pcStr + iAllocSize )
            {
                    printf ("%c", iCharVal);
                *pcStr_CurPos++ = iCharVal;
                iCharCount ++;
            }
            else
            {
                *pcStr_CurPos++ = 0;
                iCharCount ++;
                    printf ("]\n");
                goto exit;
            }

        }
            printf ("]\n");
        *pcStr_CurPos++ = 0;
        iCharCount ++;
    }
exit:

    // I allocate NOTHING, ...
    ppcStr = ppcStr_CurPos = (char**) malloc (0); // ZERO !

    // Copying pointers ...
    pcStr_CurPos = pcStr;
    while(pcStr_CurPos < pcStr + iCharCount)
    {
        //... BUT IT WORKS AND DON'T CRASH.
        // HOW IS IT POSSIBLE ???
        *ppcStr_CurPos++ = pcStr_CurPos;
        while (*pcStr_CurPos++) ;
    }

    ppcStr_CurPos = ppcStr;
    iStrNum = iStrCount;

    printf ("\n Output ppcStr:\n", iCharCount );

    while(iStrNum--)
    {
        printf("[%d][%s]\n", iStrNum, *(ppcStr_CurPos++));
    }

    printf ("Press Enter key or sth\n");
    getchar();
    return 0;
}
+8  A: 

In general, C is not guaranteed to crash if you access uninitialized memory. The behavior is undefined, which means anything could happen. The compiler could make demons fly out of your nose, as they say.

novalis
Note that this is only likely if the compiler has to do effort to prevent summoning the demons.
larsmans
+1  A: 

I believe that in practice the system may allocate more memory than you requested. So here

ppcStr = ppcStr_CurPos = (char**) malloc (0); // ZERO !

the actual size of the block may be 1 or more:

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.

Thus if the returned pointer is not null, it may point to a buffer of nonzero length.

Then here

pcStr_CurPos = pcStr;
while(pcStr_CurPos < pcStr + iCharCount)
{
    //... BUT IT WORKS AND DON'T CRASH.
    // HOW IS IT POSSIBLE ???
    *ppcStr_CurPos++ = pcStr_CurPos;
    while (*pcStr_CurPos++) ;
}

after copying the 1st byte into the "0 byte" buffer, in the inner while you seem to be stepping pcStr_CurPos through till the end of the string it points to, then consequently exit from the outer loop. Thus no more bytes are copied!

So I would venture to say that in practice you didn't necessarily write to unallocated memory (although according to the above quote it is still undefined behaviour to write to that buffer - but as @novalis rightly pointed out, undefined behaviour may not necessarily result in a crash).

Péter Török