Segmentation Fault when access to a pointer of struct in struct - c

I have an issue with pointers to struct that have members that are pointers to struct too.
Browsing the suggested similar questions I found out this:
Accessing elements within a pointer of a struct inside another pointer to a struct
where people suggest to pay attention to allocation memory of the structure.
I think this is done correctly in my code.
typedef struct {
int id_vec;
float *vec_value;
} Vector;
typedef struct cluster{
int id_cluster;
float *centroid;
Vector *patternInCluster;
} Cluster;
int main(void){
Cluster *cluster_ptr= malloc(3 * sizeof(Cluster));
if (cluster_ptr==NULL){
printf("NULL");
}
cluster_ptr->patternInCluster=malloc(2 * sizeof(Vector *));
if (cluster_ptr->patternInCluster==NULL){
printf("NULL");
cluster_ptr->patternInCluster=NULL;
}
float p1[3]={0.0f,1.0f,2.0f};
Vector *somePattern=malloc(2 * sizeof(Vector));
somePattern[0].id_vec=1;
somePattern[0].vec_value=p1;
somePattern[1].id_vec=2;
somePattern[1].vec_value=p1;
}
Then I expect that this statement works:
cluster_ptr[1].patternInCluster[1]=somePattern[1];
But it compiles and produces a Segmentation Fault.
Unexpectedly, the following statement doesn't get errors:
cluster_ptr[0].patternInCluster[1]=somePattern[1];
and a test show me correct result(somePattern[1] id and value)
I tried to debug with gdb but I only can see this:
Program received signal SIGSEGV, Segmentation fault.
0x00005555555547fe in main () at test_struct.c:36
36 cluster_ptr[1].patternInCluster[1]=somePattern[1];
Am I missing some allocation mistakes?

It's because you're not populating things fully.
This line
cluster_ptr->patternInCluster=malloc(2 * sizeof(Vector *));
is the same as saying
cluster_ptr[0].patternInCluster=malloc(2 * sizeof(Vector *));
and really given that cluster_ptr has been allocated as 3 Cluster it would be more clearer in your code to do the latter.
Since cluster_ptr[1].patternInCluster hasn't been given a value, trying to dereference it will lead to undefined behaviour but more likely will result in a segmentation fault.

You do not allocate enough memory:
cluster_ptr->patternInCluster=malloc(2 * sizeof(Vector *));
With patternInCluster being of type Vector *, you should allocate memory to hold elements of type Vector, not Vector*.
cluster_ptr->patternInCluster=malloc(2 * sizeof(Vector));

Your problem is NOT accessing the pointer inside the struct. Your problem is how you are using malloc().
When you have one pointer, you malloc only once:
int *pointer = (int* )malloc(sizeof(int));
*pointer = 1;
printf("*pointer:%d\n", *pointer);
When you have pointer-to-pointer, you malloc() once for the **pointer_to_pointer, but you also have to malloc() once for the *pointer_to_pointer:
int** pointer_to_pointer = (int** )malloc(sizeof(int*));
*pointer_to_pointer = (int* )malloc(sizeof(int));
**pointer_to_pointer = 2;
printf("**pointer:%d\n", **pointer_to_pointer);
And if you have more than one pointer, at the location pointed to by **pointer_to_pointer, you need a for loop to assign memory to every one of those *pointer_to_pointers.
for (unsigned int i = 0; i < 3; i++)
{
*(pointer_to_pointer + i*sizeof(int)) = (int* )malloc(sizeof(int));
}
**(pointer_to_pointer + sizeof(int)) = 3;
**(pointer_to_pointer + 2UL*sizeof(int)) = 4;
printf("**(pointer_to_pointer + sizeof(int):%d\n", **(pointer_to_pointer + sizeof(int)));
printf("**(pointer_to_pointer + 2UL*sizeof(int):%d\n", **(pointer_to_pointer + 2UL*sizeof(int)));
You are mistaken to think that Cluster *cluster_ptr= malloc(3 * sizeof(Cluster)); will automatically/magically assign memory for Cluster[0] and Cluster[1] and Cluster[2].
Your statement actually assigns memory only for Cluster[0], but big enough for 3 Clusters.
So the the modified code will look like this:
#include <string.h>
#include <stdio.h>
#include <malloc.h>
typedef struct {
int id_vec;
float *vec_value;
} Vector;
typedef struct cluster{
int id_cluster;
float *centroid;
Vector **patternInCluster;
} Cluster;
int main(void){
Cluster **cluster_ptr = (Cluster **)malloc(sizeof(Cluster*));
for (long unsigned int i = 0; i < 3; i++) {
cluster_ptr[i] = (Cluster *)malloc(sizeof(Cluster));
if (cluster_ptr[i]==NULL){
printf("NULL");
}
cluster_ptr[i]->patternInCluster = (Vector **) malloc(sizeof(Vector*));
for (long unsigned int j = 0; j < 3; j++) {
(*cluster_ptr)->patternInCluster[j] = (Vector *) malloc(sizeof(Vector));
if ((*cluster_ptr)->patternInCluster[j]==NULL){
printf("NULL");
(*cluster_ptr)->patternInCluster[j]=NULL;
}
}
}
float p1[3]={0.0f,1.0f,2.0f};
Vector *somePattern= (Vector *) malloc(sizeof(Vector));
somePattern[0].id_vec=1;
somePattern[0].vec_value=p1;
somePattern[1].id_vec=2;
somePattern[1].vec_value=p1;
cluster_ptr[1]->patternInCluster[1] = &somePattern[0];
cluster_ptr[0]->patternInCluster[1] = &somePattern[1];
cluster_ptr[1]->patternInCluster[0] = &somePattern[1];
cluster_ptr[2]->patternInCluster[1] = &somePattern[0];
printf("%d\n", cluster_ptr[1]->patternInCluster[1]->id_vec);
printf("%d\n", cluster_ptr[0]->patternInCluster[1]->id_vec);
printf("%d\n", cluster_ptr[1]->patternInCluster[0]->id_vec);
printf("%d\n", cluster_ptr[2]->patternInCluster[1]->id_vec);
return 0;
}
On my system, I just compiled and it builds and runs error-free.

Related

Inserting and Manipulating Dynamic Array of Struct Pointers

Here is what I am trying to do:
1. Create an array of struct pointers.
2. Fill the array with malloc'd structs.
3. Then replace one element in the array with a new malloc'd struct
4. Have no memory leaks.
I have written a test program below, but I am getting seg faults due to invalid reads and writes on my call to memcpy. What am I doing wrong?
#include <stdlib.h>
#include <string.h>
struct my_struct {
int a;
int b;
};
int main(int argc, char *argv[])
{
struct my_struct **my_arr;
my_arr = (struct my_struct **) malloc(10 * sizeof(struct my_struct *));
int i;
for (i = 0; i < 10; i++) {
struct my_struct *my_str = (struct my_struct *) malloc(sizeof(struct my_struct *));
my_arr[i] = my_str;
}
free(my_arr[0]);
memcpy(my_arr[0], my_arr[1], sizeof(struct my_struct *) * 9);
my_arr[9] = (struct my_struct *) malloc(sizeof(struct my_struct *));
for (i = 0; i < 10; ++i) {
free(my_arr[i]);
}
free(my_arr);
}
free(my_arr[0]);
memcpy(my_arr[0], my_arr[1], sizeof(struct my_struct *) * 9);
This is problem , you first free(my_arr[0]) and then copy my_arr[1] at address it points to .
You are not supposed to access memory after freeing it .
And also specified in manpage
[...]The memory areas must not overlap. Use memmove if the
memory areas do overlap.
again you do this -
my_arr[9] = (struct my_struct *) malloc(sizeof(struct my_struct *));
thus , loosing reference to previous memory block it was pointing to .
This code works and I cleaned it up a bit:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct my_struct {
int a;
int b;
};
int main(){
const int structsz=sizeof(struct my_struct);
struct my_struct **my_arr=malloc(10 * structsz);
int i;
printf("Before\n");
for (i = 0; i < 10; i++){
my_arr[i]=malloc(structsz);
my_arr[i]->a=20+i;
my_arr[i]->b=10+i;
printf("i=%d a=%d, b=%d\n",i,my_arr[i]->a,my_arr[i]->b);
}
free(my_arr[9]);
my_arr[9]=malloc(structsz);
memcpy(my_arr[9], my_arr[1], structsz); //make 1st struct in array equal the 9th
free(my_arr[8]);
my_arr[8]=malloc(structsz);
memcpy(my_arr[8], my_arr[2], structsz); //make 2st struct in array equal the 8th
printf("After\n");
for (i = 0; i < 10; ++i) {
printf("i=%d a=%d, b=%d\n",i,my_arr[i]->a,my_arr[i]->b);
free(my_arr[i]);
}
free(my_arr);
return 0;
}
The reason why the third parameter of memcpy must be the same as the size of the structure is because both pointers in memcpy are the type of struct.
If the 3rd parameter is too large, then you can run into segmentation faults because you could try to copy memory that you're not allowed to access, or at best, you could be modifying other structs in your program.
If the 3rd parameter is too small, then you could receive invalid or insufficient data.

Creating function out of realloc() function

I would like to create a function that will reallocate 2D array of typedef struct
typedef struct hero_data{
char name[254];
char title[254];
int encoding;
int startstr;
double incstr;
int startdex;
double incdex;
int startintel;
double incintel;
int basemindmg,basemaxdmg;
double bat;
double basearmor;
struct hero_data *next;
struct hero_data *Class;
}hero;
typedef struct parameters{
int toughtotal;
int nimbletotal;
int smarttotal;
int skeptictotal;
int mystictotal;
int cursedtotal;
int brutetotal;
int shreddertotal;
int vanillatotal;
int typetotal;
int typenum;
hero **smart[];
hero **nimble[];
hero **tough[];
hero **type[][];
hero **skeptic[][];
hero **mystic[][];
hero **cursed[][];
hero **brute[][];
hero **shredder[][];
hero **vanilla[][];
}Parameters;
void reallocation(Parameters *p, int typenum,int typetotal)
{
int i;
p = realloc(p,sizeof(Parameters *) * typenum);
for ( i = 0; i < typenum; i++)
{
p[i] = realloc(p[i],sizeof(Parameters) * typetotal);
}
}
The function above shall be called like: void reallocation(p->type,p->typenum,p->typetotal);
So, by substituting the parameters of the function correctly, I expect the function to look like:
void reallocation(Parameters *p, int typenum,int typetotal)
{
int i;
p->type = realloc(p->type,sizeof(Parameters *) * p->typenum);
for ( i = 0; i < p->typenum; i++)
{
p->type[i] = realloc(p->type[i],sizeof(Parameters) * p->typetotal);
}
}
The typedef struct named Parameters contains int typenum, int typetotal, and the 2D arrays that shall be initialized through realloc().
When I try to compile, I am getting an error in Tiny C (Windows): *The file is in C.
Error: cannot cast 'struct parameters' to 'void *'
(This apeears in the 'p[i] = realloc(p[i],sizeof(Parameters) * typetotal')
Can anyone help me re-write this function so that I will be able to realloc the 2D arrays within the Parameter *p?
I tried changing void reallocation(Parameters *p, ...) into void reallocation(Parameters *p[], ...) and the Error # 2 becomes the same message as Error #1 and it appears in the = of p[i] = realloc (...);
A large problem with your code is that you are assigning inequal types to each other, and you are also not checking the result of realloc. If this call were to fail, you will leak the memory allocated initially.
Assuming that your struct looks like
typedef struct {
int typenum;
int typetotal;
} Parameters;
Parameters *p;
p = malloc(10 * sizeof(*p));
if (p == NULL)
printf("Allocatation of memory failed!\n");
To properly reallocate to say 20, you could do something like this
reallocate_p(&p, 20);
Where the function is defined as
void reallocate_p(Parameters **p, int new_size)
{
Parameters *temp;
temp = realloc(*p, sizeof(*temp) * new_size);
if (temp==NULL) {
printf("Reallocatation of memory failed!\n");
// Handle error
}
*p = temp;
return;
}
Also note that we don't cast the return value of malloc() and realloc().
As to why, see this reference
OP is coding in C, but using a using a C++ compiler.
Code in C++
// C
// p = realloc(p,sizeof(Parameters *) * typenum);
// C++
p = (Parameters *) realloc(p,sizeof(Parameters *) * typenum);
OR
VS2012: set properties for each C file to use C compiler
How to compile C in visual studio 2010?
OP code has a memory leak when scaling down the pointer array table. The pointers in the table that are about to be loss due to realloc() need to be freed first.
for (i=old_typenum; i<typenum; i++) free(p[i]);
p = realloc(p,sizeof(Parameters *) * typenum);

Initializing values at the end of a pointer to pointer to pointer chain

Alright I've been cranking away at this all day (not hw), and though it may not be a particularly useful bit of code, it is a neat conceptual thing. I am trying to figure out the best way to set a value at the end of, for lack of a better name, a pointer to pointer to pointer chain. For example, I declare:
int *****ptr;
What is the best way to set each pointer to pointer segment, all the way down to the actual int value?
This code doesn't compile because it doesn't like the way I use and dereference void pointers:
#include <stdio.h>
#include <stdlib.h>
#define NUMPOINTERS 5
int main(int argc, char **argv)
{
int *****number;
*****number = malloc(sizeof(void*));
void *ptr = *number;
int i;
for(i = 1; i < NUMPOINTERS; i++)
{
if(i == NUMPOINTERS - 1)
{
ptr = malloc(sizeof(int));
int *iPtr = (int*)ptr;
*iPtr = 900;
break;
}
*ptr = malloc(sizeof(void*));
ptr = **ptr;
}
printf("%d", *****number);
return 0;
}
Is there some article out there that talks about ridiculous numbers of pointers to pointers and how to work with them?
What you have is pretty close. You probably want to work from the inside out, though. Here's a complete example based on your program (comments inline):
#include <stdio.h>
#include <stdlib.h>
#define NUMPOINTERS 5
int main(void)
{
void *ptr = malloc(sizeof(int)); // allocate space for the integer value
*(int *)ptr = 900; // initialize it
// iterate to create the nested pointers
for (int i = 1; i < NUMPOINTERS; i++)
{
void **newptr = malloc(sizeof(void *)); // create a new pointer
*newptr = ptr; // point it at what we have so far
ptr = newptr; // "step out" one level
}
int *****number = ptr; // make our 'int *****' pointer
printf("%d\n", *****number); // dereference and print the pointed-to value
return 0;
}

what is causing segmentation fault in c code, dynamic allocation accross functions

I am trying to have dynamically allocate arrays of structures and perform operations on them but i keep running into segmentation faults. could someone help me out?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void *malloc(size_t size);
typedef struct {
double x;
double y;
} coords;
struct figure {
char fig_name[128];
int coordcount, size_tracker;
coords *pointer;
} fig;
void init_fig(int n, struct figure **point)
{
printf("%u\n", sizeof(coords));
point[n]->pointer = malloc(sizeof(coords) * 20); <-------SEGFAULT
if (point[n]->pointer == NULL){
exit(-1);
}
point[n]->pointer[19].x = 2;
point[n]->pointer[0].x = 1;
point[n]->pointer[0].y = 2;
point[n]->pointer[7].x = 100;
}
int main()
{
int numfigs = 1;
struct figure * point;
point = malloc(sizeof(struct figure) * 16);
point = &fig;
point[1].coordcount = 1;
init_fig(numfigs, &point);
return 0;
}
I labelled where the first seg fault occurs, (used ddd). what i dont get is that i can manipulate point[1] in main but not in any other function.
I agree with #Maxim Skurydin.
Nevertheless I'd like to explain your mistake in some more details.
Reading your init_fig one assumes that the parameter you pass struct figure **point - is actually array of pointers to struct figure. And this function accesses its n'th element.
However in your main you do something else. You allocate an array of struct figure, and your point variable points to its head. Then you take the address of this local variable and call your init_fig.
Here's the problem. init_fig assumes that you pass it an array of pointers, whereas actually this "array" consists of a single element only: the local point variable declared in main.
EDIT:
How to do this properly.
Leave main intact, fix init_fig.
This means that actually there's an array of figure structs. Means - a single memory block, interpreted as an array of consequent structs.
void init_fig(int n, struct figure *point)
{
printf("%u\n", sizeof(coords));
point[n].pointer = malloc(sizeof(coords) * 20); <-------SEGFAULT
if (point[n].pointer == NULL){
exit(-1);
}
point[n].pointer[19].x = 2;
point[n].pointer[0].x = 1;
point[n].pointer[0].y = 2;
point[n].pointer[7].x = 100;
}
Leave init_fig intact. Fix main.
This means that we actually should allocate an array of pointers, every such a pointer should point to an allocated point structure.
int main()
{
int numfigs = 1;
struct figure ** point;
point = malloc(sizeof(struct figure*) * 16);
for (i = 0; i < 16; i++)
point[i] = malloc(sizeof(struct figure));
point[1].coordcount = 1;
init_fig(numfigs, &point);
return 0;
}
You allocate memory and store the pointer in point but then you forget that pointer when you assign &fig to it.
point = malloc(sizeof(struct figure) * 16);
point = &fig;
So, you are essentially trying to write fig[1], that does not make sense.
struct figure * point;
point = malloc(sizeof(struct figure) * 16);
here point is pointer pointing to memory of 16 structures in heap
but in the next line you have done this
point = &fig;
so its memory leak and also point is not pointing to that allocated region anymore
and also init_fig should be like this
void init_fig(int n, struct figure **point)
It's the problem of segfault
Eliminate this line point = &fig;
and modify the function:
void init_fig(int n, struct figure *point)
{
...
point[n].pointer = (coords*) malloc(sizeof(coords) * 20);
...
}
since you should pass an array of structs and not an array of pointers.
Also, add a third parameter to the init_fig function so you can pass the size of the array of points that you want to create. Like :
void init_fig(int n, struct figure *point, int size)
{
...
point[n].pointer = (coords*) malloc(sizeof(coords) * size);
...
}
Therefore, making the function more reusable.
Modify also the call to that function:
init_fig(numfigs, &point); to init_fig(numfigs, point);

how to return 1000 variables from a function in C?

How to return 1000 variables from a function in C?
This is an interview question asked which I was unable to answer.
I guess with the help of pointers we can do that. I am new to pointers and C can anyone give me solution to solve this problem either using pointers or different approach?
Pack them all in a structure and return the structure.
struct YourStructure
{
int a1;
int b2;
int z1000;
};
YouStructure doSomething();
If it's 1000 times the same type (e.g. int's):
void myfunc(int** out){
int i = 0;
*out = malloc(1000*sizeof(int));
for(i = 0; i < 1000; i++){
(*out)[i] = i;
}
}
This function allocates memory for 1000 integers (an array of integers) and fills the array.
The function would be called that way:
int* outArr = 0;
myfunc(&outArr);
The memory held by outArr must be freed after use:
free(outArr);
See it running on ideone: http://ideone.com/u8NX5
Alternate solution: instead of having myfunc allocate the memory for the integer array, let the caller do the work and pass the array size into the function:
void myfunc2(int* out, int len){
int i = 0;
for(i = 0; i < len; i++){
out[i] = i;
}
}
Then, it's called that way:
int* outArr = malloc(1000*sizeof(int));
myfunc2(outArr, 1000);
Again, the memory of outArr must be freed by the caller.
Third approach: static memory. Call myfunc2 with static memory:
int outArr[1000];
myfunc2(outArr, 1000);
In that case, no memory has to be allocated or freed.
Array Pointer approach:
int * output(int input)
{
int *temp=malloc(sizeof(int)*1000);
// do your work with 1000 integers
//...
//...
//...
//ok. finished work with these integers
return temp;
}
Struct pointer approach:
struct my_struct
{
int a;
int b;
double x;
...
//1000 different things here
struct another_struct;
}parameter;
my_struct * output(my_struct what_ever_input_is)
{
my_struct *temp=malloc(sizeof(my_struct));
//...
//...
return temp;
}
This is how you do it in C.
void func (Type* ptr);
/*
Function documentation.
Bla bla bla...
Parameters
ptr Points to a variable of 'Type' allocated by the caller.
It will contain the result of...
*/
If your intention wasn't to return anything through "ptr", you would have written
void func (const Type* ptr);
instead.

Resources