Accessing points inside structs inside unions - C - 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

Related

Having trouble allocating memory for my double pointer in structure

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);

Freeing array of structs inside struct

I have two structs
struct obj_t {
int id;
float x;
float y;
};
struct cluster_t {
int size;
int capacity;
struct obj_t *obj;
};
As you can see, there is pointer to first obj_t inside cluster_t
What I want to do is to free every obj_t from array inside cluster_t
Do I have to write it with for loop like this?
void clear_cluster(struct cluster_t *c)
{
for(int i = 0; i<c->size;i++)
{
free(&c->obj[i]);
}
free(c->obj);
}
Or is it ok to free the memory just like this ?
void clear_cluster(struct cluster_t *c)
{
free(c->obj);
}
There should be one free() for every malloc() you have, and executed in the opposite order from which it was allocated.
The field obj of cluster_t is a pointer to an array of object_t. This is probably allocated with one malloc() when initializing your cluster_t (something like c->obj = malloc(c->capacity*sizeof(*c->obj))), so it only needs to be freed with one call to free(). You would then want to free the cluster_t allocation itself (assuming it too was dynamically allocated):
free(c->obj);
free(c);
There would be a difference, however, if each object_t itself had a dynamic allocation within it. (In your example, object_t does not.) In that case, you would have needed to iterate through the array and malloc() an allocation when you created the array, and therefore do the reverse and free() each at the end.
It depends on how you allocated. It seems you did something like
struct cluster_t cluster;
cluster.obj = malloc(sizeof (struct obj_t) * SOMENUMBER);
in this case, cluster.obj is just a pointer to an array. All you need to do is
free(cluster.obj)
or
free(c->obj)
in that function which receives a pointer to c.
You only have to iterate over the array calling free if you have an array of pointers.
Remember that & takes the memory address of the variable. You don't free the pointer, you free the memory that the pointer points to. You will never do something like free(&pointer).

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);
}

Problem when typecasting a void * pointer used inside a structure to an int * pointer!

My code is as follows,
#include<stdio.h>
struct data
{
int a ;
void *b;
};
int main()
{
struct data *d;
int *ptr;
int key=10000;
d->b=&key;
ptr=(int *)d->b;
printf("%d\n",*ptr);
}
And i get a segmentation fault!! Any idea why?? Thanks in advance for any help
struct data *d merely declares a pointer. You have not allocated this struct anywhere. You need to either malloc it or declare it just as struct data d on the stack or globally.
The former can be done like this:
d = malloc(sizeof(struct data));
If you choose the latter, accessing b has to be written as d.b.
You are not allocating any memory for d. It likely points to an invalid memory area and so - segmentation fault.
You can solve this like so:
struct data *d = malloc(sizeof(*d));
You are getting segmentation fault at the line d->b=&key; Note that you have not allocated any memory location to the structure variable d. So d contains some garbage value, and d->b it trying to use that garbage address to dereference the pointer and get the component b. Here is where you get the segfault. Either statically allocate the struct variable, or use malloc to dynamically allocate it.
int main()
{
struct data *d;
int *ptr;
/* Here you are allocating memory to the
* pointer variable, which will be used to
* point to the structure type data
*/
d = malloc (sizeof (struct data));
int key=10000;
/* Now you can dereference the pointer
* and get any of the components of the
* structure, because 'd' contains a valid
* address.
*/
d->b=&key;
ptr=(int *)d->b;
printf("%d\n",*ptr);
/* Good practice to free the memory location
* you have allocated. Not freeing will lead to
* memory leak in larger applications. After you
* free the memory location denoted by the address
* stored in 'd', you will not be anymore access
* the contents of it.
*/
free (d);
/* d->b; or d->a; is no more possible at this point
* as we have freed the memory pointed by 'd'
*/
}
Or you can use:
int main()
{
/* Not a pointer, statically allocated */
struct data d;
int *ptr;
int key=10000;
d.b=&key;
ptr=(int *)d.b;
printf("%d\n",*ptr);
}
So, it is not the typecasting of void * to int * that causes the segfault. Its the illegal memory reference of the pointer variable which you have used but not allocated/initialized.
The problem is that you didn't allocate memory for a d pointer: struct data *d;. This lines only creates a pointer, it doesn't alloc memory for it. Please try the following code:
int main()
{
struct data *d = (struct data*)malloc(sizeof(struct data));
int *ptr;
int key=10000;
d->b=&key;
ptr=(int *)d->b;
printf("%d\n",*ptr);
free(d);
}

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