Memory allocation doesn't "hold" when returning to main

164 Views Asked by At

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!

3

There are 3 best solutions below

3
On

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;
}
0
On

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;
}
0
On
//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();

}