Having trouble allocating memory for my double pointer in structure - c

I'm trying to allocate memory for a pointer, but have a reference to the address of that pointer. I'm still pretty new to C and this is my first time working with double pointers really.
So I have two structures and they look like this:
typedef struct myNodes {
int data;
struct myNodes *next;
} listElement;
typedef struct {
listElement **ptrToElements;
} myStruct;
In another file, I'm trying to dynamically allocate memory for my pointer by doing something like this:
myStruct *myStruct = malloc(sizeof(*myStruct));
*(myStruct->ptrToElements) = (listElement*)malloc(sizeof(listElement));
but I keep encountering a segmentation fault from doing so. What could be the issue? Thanks!

The problem is with
*(myStruct->ptrToElements) ....
statement. Before dereferencing myStruct->ptrToElements, you need to make sure it points to a valid memory.
To elaborate, you allocate memory for myStruct. Fine.
That constitutes allocating memory for the member ptrToElements. Good.
Question: What does ptrToElements points to?
Answer: Indeterministic.
So, when you try to derefernce a pointer which points to an indeterministic memory address, it's pretty much invalid memory address and attempt to do so will invoke undefined behavior.
Solution: You need to allocate memory for myStruct->ptrToElements before you can go ahead and dereference it.
having said that, please see do I cast the result of malloc?

You define the structure to contain a pointer to a pointer to a listElement
typedef struct {
listElement **ptrToElements;
} myStruct;
As Sourav Ghosh wrote, you try to assign a value to the pointer where ptrToElements would point to without allocating memory.
Probably you should change the pointer type to
typedef struct {
listElement *ptrToElements;
} myStruct;
and when allocating the memory
myStruct *myStruct = malloc(sizeof(*myStruct));
/* If the list can be empty, initialize root with NULL pointer */
myStruct->ptrToElements = NULL;
/* when you add the first list element */
myStruct->ptrToElements = malloc(sizeof(listElement));
myStruct->ptrToElements->data = someValue;
/* at least for the last element you add here you should initialize next */
myStruct->ptrToElements->next = NULL;
Don't forget to handle errors, e.g. malloc returning NULL.

I think this is what you want:
typedef struct myNodes {
int data;
struct myNodes *next; // not clear what this pointer is used for...
} listElement;
typedef struct {
listElement *ptrToElements;
} myStruct;
// Memory Allocation
// allocate myStruct pointing to an array of N listElements
myStruct *ms = malloc(sizeof(myStruct));
ms->ptrToElements = malloc(N * sizeof(listElement));
// element access
for (int i = 0; i < N; i++) {
listElement *le = ms->ptrToElements[i];
le->data = ...
le->next = NULL; // not clear what this pointer is used for...
}
// Memory deallocation
free(ms->ptrToElements);
free(ms);

Related

Declaring a pointer to struct creates a struct?

It seems to me like struct new_element *element = malloc(sizeof(*element)) creates a structure of type element, whereas I thought it would only create a pointer to it. The following code proves to me I'm wrong:
struct new_element
{
int i;
struct new_element *next;
};
int main(void)
{
struct new_element *element = malloc(sizeof(*element));
element->i = 5;
element->next = NULL;
printf("i = %d, next = %p\n", element->i, element->next);
}
Output:
i = 5, next = (nil);
element->i was given the value 5 and element->next was given the value NULL. Doesn't that mean that element points to a structure, which would mean that there is a structure that was created? I thought that malloc would only give a pointer the size needed in memory.
The variable element is a pointer. When you define it, that sets aside space for the pointer.
If you just did this:
struct new_element *element;
You've created a pointer. It just doesn't point anywhere.
When you then call malloc(sizeof(*element)), that sets aside space big enough for what element points to, i.e. an instance of struct new_element. You then point the variable element to this section of memory.
This syntax:
element->i = 5;
Is the same as:
(*element).i = 5;
It dereferences the pointer element, giving you a struct new_element, then you access the member i.
If you did this, as you suggested in the comments:
struct new_element *element = malloc(sizeof(element));
You're not allocating the proper amount of space. You're setting aside enough space for a struct new_element * instead of a struct new_element. If the struct is larger than a pointer to it (likely in this case, since it contains a pointer to its own type), then you end of writing past the end of the allocated memory when modifying one of the members. This invokes undefined behavior.

Allocating memory for a structure within a structure

typedef struct{
char id[15];
int count;
}hashtag;
typedef struct node{
hashtag *hashtag;
struct node*next;
}*link;
I'm writing a program to read hashtags from a sentence, and I want to store them in a list. I've already defined this two structures, and I can read and pass the hashtags to the function below but I need help allocating memory in order to copy the string to the list.
void check_insert(char newh[]){
link x;
//malloc to allocate memory for the string I want to copy
strcpy(x->hashtag->id, newh);
x->hashtag->count += 1;
head = insert_end(head, x->hashtag); //head is a global variable that points to the 1st element of the list
}
You should allocate and initialize the pointer x in check_insert, it is undefined behavior to dereference it and access its members without allocation first:
void check_insert(char newh[]){
link x = malloc(sizeof *x);
x->hashtag = malloc(sizeof *x->hashtag);
// strcpy(x->hashtag->id, newh); <-- UB if newh is larger than 14 in size
x->hashtag->id[0] = '\0';
strncat(x->hashtag->id, newh, sizeof(x->hashtag->id));
x->hashtag->count = 1;
head = insert_end(head, x->hashtag);
}

Accessing points inside structs inside unions - C

I have the following data structures
struct a_str {
union {
struct {
struct c_str *c;
} b_str;
struct {
int i;
} c_str;
};
}
struct c_str {
struct d_str;
}
struct d_str {
int num;
}
I am trying to access num in struct d_str. For some reason I keep on getting a segmentation fault.
struct a_str *a = init_a(); //assume memory allocation and init is ok.
a->b_str.c->d_str.num = 2;
What is wrong?
Probably you are not allocating memory for a->b_str.c in your init() function, that may be reason that a->b_str.c is pointing a garbage location and segmentation fault is due to accessing memory that is not allocated - an illegal memory operation.
If init() function is correct, there should not be any problem (syntax-wise your code is correct).
Below I have suggested inti() function that will allocated memory for your nested structure correctly (read comments).
struct a_str *init()
{
struct a_str *ret = malloc(sizeof(struct a_str)); // memory for `struct a_str`
struct c_str *cptr = malloc(sizeof(struct c_str)); // memory for inner struct
ret->b_str.c = cptr; //assigning valid memory address to ret->b_str.c
return ret;
}
Below is the main() code with steps for deallocate/free() dynamically allocated memory.
int main(int argv, char **argc)
{
struct a_str *ret = init();
ret->b_str.c->d.num = 5;
printf("%d\n", ret->b_str.c->d.num);
//Make sure to free the memory allocated through malloc
free(ret->b_str.c); // 1 first free in struct
free(ret); // in reverse order of allocation
return 0;
}
struct a_str *a = init_a();
My guess: Your init_a function
is allocating the a_str pointer
is not allocating the a->b_str.c pointer
Since a->b_str.c is not allocated, when you want to access it, a segfault occur
EDIT :
Second guess: Your init_a function
is allocating the a_str pointer
is allocating the a->b_str.c pointer
is initializing the a->c_str.i integer value
By initializing c_str.i value, it erase the b_str.c value Since it share the same location (it is a union).
you need to check your pointer "c" if it has been initialized

Setting a pointer to null segfault

I have a struct called node as follows:
struct node {
int data;
}
stored in some structure:
struct structure {
struct node *pointer;
}
I'm trying to set pointer to NULL as follows:
struct structure *elements;
elements->pointer = NULL;
Why does this segfault? Does it actually attempt to dereference the pointer before setting it to null?
When I switch elements from a pointer to the actual struct and do the following:
struct structure elements;
elements.pointer = NULL;
It stops segfaulting and works. Why doesn't setting a pointer to null work?
struct structure *elements;
elements->pointer = NULL;
elements pointer points to nowhere. Dereferencing an invalid pointer (elements pointer) is undefined behavior.
You need to initialize elements pointer to a valid object, like:
struct structure my_struct;
struct structure *elements = &my_struct;
elements->pointer = NULL;
You need to initialize the pointer
struct structure *elements = malloc(sizeof(struct structure));
If you don't do this it will point to a arbitrary memory location.
The invalid pointer you're derefrencing, thus the segfault, is not elements->pointer, but elements itself. Since it has not been set (e.g.: by a malloc), it could point to any location in memory.
you didn't initialize *elements.
*elements right now points to nothing, so elements->pointer is dereferencing nothing, which gives you your segfault.
elements hasn't been initialized to point to anything yet.

whats wrong in this program?

Am unable to run this code...
#include<cstdio>
int main()
{
struct a{
int b;
struct a *next;
};
typedef struct a no;
no *n;
n->b = 12;
n->next = NULL;
n->next->b = 12;
n->next->next = NULL;
printf("%d %d", n->b, n->next->b);
getchar();
return 0;
}
When you say:
no *n;
you get an uninitialised pointer. When you use that pointer, you get undefined behaviour.
You allocated space for a pointer to a structure, but you didn't allocate space for the actual structure. This means that you don't have a memory address for the structure you are using.
In addition, the pointer points to some random memory address because you didn't initialize it. As a result, you could be trying to read and write to memory that doesn't belong to you, which can cause your program or even your system to crash because of the undefined behavior that results.
As #Neil Butterworth said, you get an uninitialised pointer. This mean that this pointer could point to anywhere, thus giving an access violation error. The way to fix this is simple, just call malloc() before using that pointer. malloc() gives that pointer a valid and usable address, so no one will complain about that.
You're declaring a struct INSIDE a function.
Declare the struct OUTSIDE of the function.
The typedef should be declared outside the function too.
#include<cstdio>
struct a{
int b;
struct a *next;
};
typedef struct a no;
int main()
{
///... your code...
}
try something like this:
no *n = (no*)malloc(sizeof(no));
#include <cstdio>
/* declaring the struct in the function definition may be possible (I'm not sure,
actually, haha). Unless you have a GOOD reason, it's good practice to declare
structs, globals, typedefs, etc... outside the function */
typedef struct a{
int b;
struct a *next;
} no;
int main()
{
no *n;
/* Here, you have a pointer. Remember these are simply (generally) 32-bit values
defined in your stack space used to store a memory location which points to your
ACTUAL struct a! Depending on what USED to be in the stack space, this could
point ANYWHERE in memory, but usually you will find that it points to the NULL
memory location, which is just address "0". To get this to point to something,
you have to allocate empty space on your heap to store your struct... */
n = malloc(sizeof(no));
/* Now your pointer n points to an allocated 'struct a', and you can use it like
normal */
n->b = 12;
n->next = NULL;
/* You just set n->next, which is another 'no' pointer, to NULL. This means that
n->next points nowhere. So, just like above you have to malloc another instance
of the struct! */
n->next = malloc(sizeof(no));
/* NOW you can use n->next with no ill effects! */
n->next->b = 12;
n->next->next = NULL;
printf("%d %d", n->b, n->next->b);
getchar();
/* After you're done with your structs, you want to free them using the POINTERS
that reference them */
free(n->next);
free(n);
return 0;
}

Resources