1

I have a homework assignment and within it I need to allocate memory to a pointer which points to an array of pointers (pNode**). Below is the function which receives an array of an array of pointers, and allocates memory for it and all the relevant pointers & data inside.

In short, the function should allocate memory for a pointer that points to an array of Node pointers.

**NOTE: I have removed certain elements from the function which are irrelevant to my question. The function newGNode allocates memory for the Node struct

int getChildren(pNode** childrenNodes)
{
    *childrenNodes = (pNode*)malloc(sizeof(pNode));
    for (int i = 0; i < NUM_OF_CHILDREN; i++)
    {
        childrenNodes[i] = (pNode *)newGNode();
    }
    return numOfChildren;
}

This is how I call it within the main function:

int main()
{
    pNode * ng = NULL;
    int test = getChildren(&ng);

}

No matter what I tried to do I cannot seem to get the allocation "stick" in the main function. Inside the getChildren function I can see within the debugger that memory has been allocated precisely as I want it. However when the function returns to the main, the ng pointer seems to be corrupted since the debugger is telling me that it is unable to read the memory.

I have searched online and tried different things but none seem to work. Does anyone have any idea why this is not working as intended? I'm guessing something within the memory allocation is wrong, but can't seem to figure out what.

Here is one question which is similar to mine, but it didn't really help me

Thank you!

Community
  • 1
  • 1
user475680
  • 679
  • 1
  • 9
  • 21
  • 2
    You pass two arguments, but the prototype has one. Maybe you forgot something in your post. – gsamaras Nov 21 '14 at 09:40
  • As a sidenote: you shouldn't cast the result of `malloc` http://c-faq.com/malloc/mallocnocast.html – eerorika Nov 21 '14 at 09:41
  • 2
    Are you using C or C++? You should avoid malloc in C++ (and in Modern C++, new). – The Forest And The Trees Nov 21 '14 at 09:43
  • @G.Samaras Yes thank you, fixed the post (the second param was unused anyway) – user475680 Nov 21 '14 at 09:44
  • @TheForestAndTheTrees Using C, I know I should be using calloc but this is one of the course's requirements... – user475680 Nov 21 '14 at 09:45
  • 1
    @user475680 I don't think he meant that you should use calloc instead of malloc. You shouldn't use any of [re|m|c]alloc in c++ at all (barring exceptional cases). If you don't use c++, don't tag the question with c++. – eerorika Nov 21 '14 at 09:50
  • Can you use a real 2D array instead of a pointer array? Then there are far more elegant ways. http://stackoverflow.com/questions/12462615/how-do-i-correctly-set-up-access-and-free-a-multidimensional-array-in-c – Lundin Nov 21 '14 at 10:25
  • @Lundin No unfortunately this is how i must do it (Exercise requirements) – user475680 Nov 21 '14 at 12:16

3 Answers3

3

1) You call getChildren() with two arguments, but it is expecting only one:

int getChildren(pNode** childrenNodes)

2) You want an array but reserve space for a single pNode:

*childrenNodes = (pNode*)malloc(sizeof(pNode));

Change to

*childrenNodes = malloc(sizeof(pNode) * NUM_OF_CHILDREN); /* Don't cast malloc */

EDIT:

It seems that you want an array of pointers, then ng must be declared as:

pNode **ng = NULL; /* pointer to pointer */

you need 3 levels of indirection to receive ng:

int getChildren(pNode ***childrenNodes)

and reserve space for an array of pointers:

*childrenNodes = malloc(sizeof(pNode *) * NUM_OF_CHILDREN);

An example with ints:

#include <stdio.h>
#include <stdlib.h>

int arr[] = {1, 2};

void func(int ***p)
{
    *p = malloc(sizeof(int *) * 2);
    (*p)[0] = &arr[0];
    (*p)[1] = &arr[1];
}

int main(void)
{
    int **p;

    func(&p);
    printf("%d %d\n", *p[0], *p[1]);
    free(p);
    return 0;
}

But *** is considered bad style, instead:

#include <stdio.h>
#include <stdlib.h>

int arr[] = {1, 2};

int **func(void)
{
    int **p;

    p = malloc(sizeof(int *) * 2);
    p[0] = &arr[0];
    p[1] = &arr[1];
    return p;
}

int main(void)
{
    int **p = func();

    printf("%d %d\n", *p[0], *p[1]);
    free(p);
    return 0;
}
David Ranieri
  • 39,972
  • 7
  • 52
  • 94
  • Yes thank you, I noticed the problematic malloc after posting. This seems to work, however there is something weird going. When I access the arrays pointers inside the main, it seems that only 3 of 5 are allocated. When i look at &ng[3] I see garbage, but when i look at &ng[0] I see actual data (0's and such) – user475680 Nov 21 '14 at 09:46
  • If you want to allocate `n` pointers use `*childrenNodes = malloc(sizeof(pNode *) * NUM_OF_CHILDREN);` (Note `pNode *` instead `pnode`), and `ng` must be declared as `pNode **ng = NULL;` – David Ranieri Nov 21 '14 at 09:52
  • The line "*childrenNodes = malloc(sizeof(pNode *) * NUM_OF_CHILDREN);" crashes Visual Studio (Unhandled Exception...), but when I remove the * and write childrenNodes =, it works OK. After reading your answer I made some adjustments, and again it seems to be OK logically, within the function the allocation seems to work OK but again, in the main function no matter what I do in the "watch" in debugging, it says Unable to Read memory – user475680 Nov 21 '14 at 11:20
0

I hope other asnwers solved your proble, but if you don't mind having an alternate approach, [without using double pointer], please consider the following code. I believe it's self explaining.

#include <stdio.h>
#include <stdlib.h>

int * alloc_memory()
{
    int * pTempInt = NULL;

    pTempInt = calloc (1, sizeof(*pTempInt));  //you can replace 1 with desired number
    printf("in alloc_memory, before alloc pInt = %p\n", pTempInt);

    return pTempInt;

}


int main()
{

    int * pInt = NULL;

    printf("in main, before alloc pInt = %p\n", pInt);
    pInt = alloc_memory();
    printf("in main, after alloc pInt = %p\n", pInt);

    free(pInt);

    return 0;
}
Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
0
//you could attack the problem directly with:
// where 'Node' is the struct tag name, 
// not a pointer to struct definition 
// and not and struct definition name 
// and not a typedef of a struct

// note:
// gdb prefers struct tag names as then it can display 
// each of the associated fields of the struct.

// also struct { ... } name; is a depreciated format in modern C

struct Node
{
    ...
};

struct Node ** getChildren( void );

struct Node ** getChildren()
{
    // get array of pointers to nodes
    struct Node ** ppChildNodes = malloc( sizeof(struct Node*)*NUM_OF_CHILDREN);

    // get struct Node size allocation for each child pointer
    for( int i=0; i< NUM_OF_CHILDREN; i++)
    {
        ppChildNodes[i] = malloc( sizeof(struct Node) );
    }
    return ppChildNodes;
}


int main()
{
    struct Node ** ng = getChildren();

}
user3629249
  • 16,402
  • 1
  • 16
  • 17