Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Need help in understanding malloc(0) for my example [duplicate]

I am trying to understand inners of double pointer (which is pointer holding another pointer) to form an array of pointers. So, I am trying to run the following code by experimenting on malloc to debugging and see how it works. I am unable to understand what malloc(0) does in my case, but my code works by outputting "Hello World".

What is the diff between

pToCharsPointers = (char**) malloc(0);

and

pToCharsPointers = (char**) malloc(2 * sizeof(char*));

Please someone clarify what it is doing in my case.

#include <stdio.h>

char **pToCharsPointers;

int main(void)
{
    pToCharsPointers = (char**) malloc(0);

    char* pToChars = "Hello";
    *pToCharsPointers = pToChars;

    *(pToCharsPointers + 1)= "World";

    printf("%s %s\n", *(pToCharsPointers + 0), *(pToCharsPointers + 1));

    return 0;
}

Also, I would really appreciate if you anyone could explain how double pointers works with an example in memory for visualizing as I fail to see myself even though I tried to read about this in many places.

EDIT: Thanks everyone for sharing your answers, and it really helped to understand. I got a valid pointer with malloc(0) when I printed it, and can dereference it also without issues during multiple tries. Wanted to understand why its working. Seems like in my case undefined behavior was actually a expected one.

like image 617
Dinesh G Avatar asked Feb 24 '17 09:02

Dinesh G


4 Answers

In your code

(char**) malloc(0);

is wrong for two reasons, like

  • Passing size as 0 is implementation defined behaviour and the returned pointer cannot be dereferenced. Quoting the manual page,

    If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be successfully passed to free().

  • Please see this discussion on why not to cast the return value of malloc() and family in C..

Any code, attempting to use the returned pointer for a code like yours, will be essentially dereferencing invalid memory which invokes undefined behavior. So, the output/behaviour of your program can neither be predicted nor reasonified.

OTOH, a statement like

pToCharsPointers = malloc(2 * sizeof(char*));

is valid but you ought to check the validity of the returned pointer to ensure malloc() is success.

like image 72
Sourav Ghosh Avatar answered Oct 04 '22 19:10

Sourav Ghosh


I will try to explain:

pToCharsPointers = (char**) malloc(0);

this line will bring to pToCharPointers a pointer that you can't use

but you can't know if an error will come. don't do that!

char* pToChars = "Hello";
*pToCharsPointers = pToChars;

this line will bring *pToCharsPointers to pToChar that pointing to the "Hello".

*(pToCharsPointers + 1)= "World";

this line will write in *(pToCharsPointers + 1), that you can't know to where it is pointing, "World". also, an option to an error but not for sure.

printf("%s %s\n", *(pToCharsPointers + 0), *(pToCharsPointers + 1));

this line will print "Hello Wolrd" if you didn't get any errors yet.

like image 42
Roy Avidan Avatar answered Oct 04 '22 21:10

Roy Avidan


It simply asks to allocate zero bytes. It is up to the implementation of malloc if it should return a null pointer or not.

Even if it returns a non-null pointer, you can't dereference it since it will automatically be out of bounds. Dereferencing the returned pointer will lead to undefined behavior in both cases.

When you do malloc(2 * sizeof(char*)) you allocate enough space for two pointers to char.

like image 32
Some programmer dude Avatar answered Oct 04 '22 21:10

Some programmer dude


You forgot to include <stdlib.h>. Calling malloc() without a proper definition has undefined behavior. Explicitly casting its return value hides the fact that the compiler may assume it returns an int value. This cast is necessary in C++, where calling a function without a prior definition is invalid, but it is counter-productive in C.

Regarding your question: allocating a block of size zero can have two possible outcomes, depending on the implementation of your C library:

  • malloc(0) can return NULL, and attempting to store values at this address has undefined behavior.
  • malloc(0) can return a valid non-null pointer, but this pointer cannot be dereferenced, nor used to store anything as the size of the object it points to is 0.

In both cases, your code has undefined behavior, which may or may not be a crash.

like image 34
chqrlie Avatar answered Oct 04 '22 21:10

chqrlie