6

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.

Dinesh G
  • 129
  • 7

4 Answers4

6

In your code

(char**) malloc(0);

is wrong for two reasons, like

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.

Community
  • 1
  • 1
Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • But my code works as expected which is why I asked this question. Can you tell me why please ? – Dinesh G Feb 24 '17 at 09:08
  • 2
    @DineshG ***Seemingly*** working okay is one of the possibilities of undefined behavior. – Some programmer dude Feb 24 '17 at 09:11
  • @DineshG Probably because your implementation doesn't return `NULL`, but some other value. You could print it. But all of **doesn't matter**, it's undefined behavior anyway. – unwind Feb 24 '17 at 09:13
  • Just to avoid any possible confusion, what @unwind meant is, _printing_ the returned pointer is OK, _dereferencing_ that is not. – Sourav Ghosh Feb 24 '17 at 09:58
  • Dear @**downvoter**, if you care to leave a comment along with the downvote it'll help me understanding the mistake and improve the post for better. Thank you. – Sourav Ghosh Feb 24 '17 at 10:03
  • @SouravGhosh The reason is your usual claim, that casting the return value is *wrong*. – Ctx Feb 25 '17 at 14:57
  • @Ctx Thanks, much appreciated. Sorry, but I stand by my statement. :) – Sourav Ghosh Feb 25 '17 at 14:59
  • 1
    @SouravGhosh No need to be sorry, freedom of speech is very precious ;) – Ctx Feb 25 '17 at 15:13
3

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.

Roy Avidan
  • 769
  • 8
  • 25
2

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.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
2

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.

chqrlie
  • 131,814
  • 10
  • 121
  • 189