Dynamic array in struct calloc or pointers failing, C - c

I'm attempting to complete an assignment on sparse matrices in C. I have a sparse matrix held as a list of values and coordinates and am converting it to Yale format.
I have run into a strange memory allocation issue that no one seems to have seen before. My code is:
yale* convertMatrix(matrix_list* input){
int matrix_elements = input->elements;
int matrix_rows = input->m;
yale* yale = (struct y*)calloc(1, sizeof(yale));
int* A = (int*)calloc(matrix_elements, sizeof(int));
int* IA = (int*)calloc(matrix_rows + 1, sizeof(int));
int* JA = (int*)calloc(matrix_elements, sizeof(int));
printf("%d elements\n",matrix_elements);
yale->A = A; // Value
yale->IA = IA; // Row (X)
yale->JA = JA; // Column (Y)
yale->elements = matrix_elements;
yale->m = matrix_rows;
yale->n = input->n;
list* tmp_list = input->first;
for(int i = 0, j = 0, tmp_y = 0; i < matrix_elements && tmp_list!=NULL; i++){
printf("Input Value: %d \n",tmp_list->point.value);
A[i] = tmp_list->point.value;
// Initialise the first row
if(i == 0) IA[0] = tmp_list->point.x;
else{
// Add a new row index
if(tmp_y != tmp_list->point.x){
j++;
IA[j] = i;
tmp_y = tmp_list->point.x;
}
}
JA[i] = tmp_list->point.y;
tmp_list = tmp_list->next;
}
for(int i = 0; i < matrix_elements; i++)
printf("%d,",yale->A[i]);
printf("\n");
for(int i = 0; i < matrix_rows + 1; i++)
printf("%d,",yale->IA[i]);
printf("\n");
for(int i = 0; i < matrix_elements; i++)
printf("%d,",yale->JA[i]);
return yale;
}
And here is the struct for yale:
typedef struct y{
int n;
int m;
int elements;
int *IA;
int *JA;
int *A;
} yale;
But the program segfaults at the first relevant printf on the first iteration of the loop.
printf("%d,",yale->A[i]);
I'm positive:
matrix_elements is an integer (9 in my test case)
matrix_rows is an integer
A / IA / JA are all filled with correct values (if you swap yale->A for A in the printf, it works fine).
Directly callocing the array to the struct pointers doesn't affect the result.
Mallocing, callocing, not typecasting, all no effect.
Thanks to Xcode and gdb I can also see that at the point of the segfault. The structure pointers do NOT seem to point to the arrays

I suggest you run your code under Valgrind. This should report the buffer overflow error. (A buffer overflow is where you write past the end of an array).
I also recommend you write some unit tests for your code. They can be very helpful detecting bugs. In particular, I suggest you write a test with a 3x3 input matrix with a value in every position. Check that the values you get out are what you expect.

To get it compiled, I need to prepend this to the snippet:
#include <stdlib.h>
#include <stdio.h>
typedef struct y{
int n;
int m;
int elements;
int *IA;
int *JA;
int *A;
} yale;
typedef struct list {
struct list *next;
struct point { int x,y,value; } point;
} list;
typedef struct matrix_list {
int elements;
int m;
int n;
struct list *first;
int *point;
} matrix_list;
UPDATE: I transformed the program into something more readable (IMHO). I don't have the faintest idea what the IA and JA are supposed to do, but the below fragment should be equivalent to the OP.
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
struct y {
unsigned int n;
unsigned int m;
unsigned int elements;
unsigned int *IA;
unsigned int *JA;
int *A;
} ;
struct list {
struct list *next;
struct point { unsigned int x,y; int value; } point;
} ;
struct matrix_list {
unsigned int elements;
unsigned int m;
unsigned int n;
struct list *first;
} ;
struct y *convertMatrix(struct matrix_list* input)
{
unsigned int matrix_elements = input->elements;
unsigned int matrix_rows = input->m;
unsigned int ii,jj,tmp_y;
struct y *yale ;
struct list *tmp_list ;
yale = calloc(1, sizeof *yale);
assert (yale != NULL);
printf("%u elements\n",matrix_elements);
yale->A = calloc(matrix_elements, sizeof *yale->A);
assert (yale->A != NULL);
yale->IA = calloc(matrix_rows + 1, sizeof *yale->IA);
assert (yale->IA != NULL);
yale->JA = calloc(matrix_elements, sizeof *yale->JA);
assert (yale->JA != NULL);
yale->elements = matrix_elements;
yale->m = matrix_rows;
yale->n = input->n;
// Initialise the first row, set start condition
// FIXME: this ignores the empty list or size=0 cases
yale->IA[0] = tmp_y = input->first->point.x;
ii = jj = 0;
for(tmp_list = input->first ;tmp_list; tmp_list = tmp_list->next) {
printf("Input Value: %d \n",tmp_list->point.value);
yale->A[ii] = tmp_list->point.value;
// Add a new row index
if(tmp_y != tmp_list->point.x){
jj++;
yale->IA[jj] = ii;
tmp_y = tmp_list->point.x;
}
yale->JA[ii] = tmp_list->point.y;
if (++ii >= matrix_elements ) break;
}
for(int i = 0; i < matrix_elements; i++)
printf("%d,",yale->A[i]);
printf("\n");
for(int i = 0; i < matrix_rows + 1; i++)
printf("%u,",yale->IA[i]);
printf("\n");
for(int i = 0; i < matrix_elements; i++)
printf("%u,",yale->JA[i]);
return yale;
}
Note: I moved the (ii == 0) {} condition out of the loop, and replaced the one-letter indices by there two-letter equivalents. Also: all the indices are unsigned (as they should be)

Related

Attempt to access elements of a 2d struct array failing

typedef struct{
unsigned long a;
unsigned long b;
unsigned long c;
} mini_struct;
struct ministruct** build_2Dstruct(unsigned long x, unsigned long y){
double x_squared = pow(2, x);
struct ministruct** temp = (mini_struct**)malloc(x*sizeof(mini_struct*));
for(int i = 0; i < x_squared; i++){
temp[i] = (mini_struct*)malloc(y*sizeof(mini_struct));
for(int j = 0; j < y; j++){
temp[i][j].a = 0;
etc....
}
}
return temp;
}
In the code above I am trying to create a 2D array of ministructs**, with the whole struct being made out of 2^x ministructs*, and each ministruct* has y amount of ministructs.
aka:
x = 2,
y = 2,
[[struct, struct], [struct, struct], [struct, struct], [struct, struct]]
However, for some reason when I try to access the second element or index 1 of the struct inside each struct*, it says there is an error: "expression must be pointer to complete object".
I just do not understand why the code is not allowing me to access each individual element of the elements of the array?
Thanks
You are trying to make an x by y array of structs. So:
// create array of x pointers
mini_struct **temp = malloc(x*sizeof(mini_struct*));
for (int i=0; i<x; i++) {
// to array of y structs
temp[i] = malloc(y*sizeof(mini_struct));
for (int j=0; j < y; j++) {
temp[i][j].a = 0;
... etc.
Question is incomplete so I will be making asumptions.
You seem to be wanting to allocate a 2D array of structs and initialize all members to 0. Here is a possible solution:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
typedef struct mini_struct{
unsigned long a;
unsigned long b;
unsigned long c;
} mini_struct;
struct mini_struct** build_2Dstruct(unsigned long x, unsigned long y){
double x_squared = pow(x, 2);
mini_struct **temp = (mini_struct **) malloc(x_squared * sizeof(mini_struct*));
for(int i = 0; i < x_squared; i++){
temp[i] = (mini_struct *) calloc(y, sizeof(mini_struct));
}
return temp;
}
int main () {
int x = 3;
int y = 4;
mini_struct **struct2D = build_2Dstruct(x, y);
int x_squared = pow(x,2);
for (int i = 0; i < x_squared; ++i) {
for (int j = 0; j < y; ++j) {
printf("Value of data stored at struct[%d][%d] is: %d\n", i, j, struct2D[i][j]);
}
}
for (int i = 0; i < x_squared; ++i) {
free(struct2D[i]);
}
free(struct2D);
}
As you can see, this contains the whole program, not just the snippet you showed. In this case, a main function would have been useful so that we don't have to guess what you want to do. My solution creates the 2D array with all elements initialized to 0 (you can use calloc to do that, no need for a second for loop).
Another important point is that, because the function returns a newly heap allocated 2D array, you need to free it to avoid a memory leak (end of main function).
You allocate x pointers to mini_struct:
mini_struct **temp = (mini_struct **) malloc(x_squared * sizeof(mini_struct*));
But then when you initialize them:
for(int i = 0; i < x_squared; i++){
temp[i] = (mini_struct *) calloc(y, sizeof(mini_struct));
}
You index temp based on upto x_squared.
Consider if x is 2. You would allocate temp to be an array of two pointers to mini_struct. But then your for loop would attempt to initialize four elements in temp.

Why do I get a segmentation fault by declaring a 2d array in c?

I am new to threads and I have a program that uses threads to find the minimum number out of a 2d array and later on, it finds the distance that the other elements of the array have from the minimum number and stores them in another array.
The user should enter the size of the array and the number of threads he wants to use.
I tried the program below for 1d array and it worked just fine. When I converted it to work for a 2d array it started crashing and throwing a segmentation fault. I, however, cannot find which part of the 2d declaration is wrong.
Any help is really appreciated.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>
#include <pthread.h>
struct Parameters
{
// input
int s,p; //n is size of array, p is number of threads
int** array; //array with elements
int start;
int end;
// output
int smallest;
int pos; //position if minimum
int** B; //array that holds the distances
};
void* min(void* args)
{
struct Parameters* p = (struct Parameters*)args;
int **array = p->array;
int **B1 = p->B;
int start = p->start;
int end = p->end;
int smallest = array[start][start];
int pos = p->pos;
int distance;
//find the smallest
for (int i = start; i < end; i++)
{
for(int j = start; j < end; j++)
{
if (array[i][j] < smallest)
{
smallest = array[i][j];
pos = i;
}
}
}
//find the distances
for(int i = 0; i < ((struct Parameters*)args) -> s; i++)
{
for(int j = 0; j < ((struct Parameters*)args) -> s; j++)
{
distance = abs(pos - i);
B1[i][j] = distance;
}
}
params->smallest = smallest;
params->B = B1;
return NULL;
}
int main()
{
int smallest,pos;
int s,p;
struct Parameters *ptr = (struct Parameters *)malloc(sizeof(struct Parameters));
if(ptr == NULL)
{
printf("Not enough. Try again \n");
exit(0);
}
printf("Type s\n");
scanf("%d",&(ptr->s));
printf("Type p\n");
scanf("%d", &(ptr->p));
// declare an array of threads and associated parameter instances
pthread_t threads[(ptr->p)];
struct Parameters thread_parameters[(ptr->p)] ;
int arr[ptr->s][ptr->s];
int B2[ptr->s][ptr->s];
// intialize the array
for(int i=0; i< ptr->s; i++)
{
for(int j=0; j< ptr->s; j++)
{
printf("Type a \n");
scanf("%d",&arr[i][j]);
}
}
// smallest needs to be set to something
smallest = arr[0][0];
// start all the threads
for (int i = 0; i < ptr->p; i++)
{
memcpy(arr, thread_parameters[i].array, sizeof(arr));
thread_parameters[i].s = ptr->s;
memcpy(Bb, thread_parameters[i].B, sizeof(B2));
thread_parameters[i].start = i * (ptr->s / ptr->p);
thread_parameters[i].end = (i+1) * (ptr->s / ptr->p);
pthread_create(&threads[i], NULL, min, &thread_parameters[i]);
}
// wait for all the threads to complete
for (int i = 0; i < ptr->p; i++)
{
pthread_join(threads[i], NULL);
}
// Now aggregate the "smallest" and "largest" results from all thread runs
for (int i = 0; i < ptr->p; i++)
{
if (thread_parameters[i].smallest < smallest)
{
smallest = thread_parameters[i].smallest;
}
}
printf("Smallest is %d\n", smallest);
thread_parameters[ptr->p].B[ptr->s][ptr->s];
for (int i = 0; i < 1; i++)
{
for(int j = 0; j < ptr->s;j++)
{
for(int k = 0; k < ptr->s; k++)
{
printf("Element %d is %d away from min\n",j,thread_parameters[i].B[j][k]);
}
}
}
return 0;
}
Thank you!!
The issue with your code might also come from :
memcpy(arr, thread_parameters[i].array, sizeof(arr));
...
memcpy(Bb, thread_parameters[i].B, sizeof(B2));
as thread_parameters[i].array and thread_parameters[i].B are not allocated, if you are only reading the array it might b fine to only pass them by address
thread_parameters[i].array = arr
but for thread_parameters[i].B you would need to allocate the arrays and perform a deep copy (memcpy would not work)
The below text does not answer the question but does provide some insight on VLA usage
One reason for causing the segmentation with a declaration of a Variable Length Array is that the value is to large to allocate the array on the stack (some compiler choose this option, this choice might have performance reason).
The is not much option to recover cleanly from failure to allocate memory on the stack as there is little way to clean up stack memory during runtime within the same stack context.
You can mitigate the issue by allocating your 2D arrays on the heap instead, some of the strategies are available here(thanks #Lundin) and here.
int** alloc_2d_int_array(size_t rows, size_t cols) {
int **result = malloc(rows * sizeof(int *));
if(result == NULL) {
// could not allocate more memory
return NULL;
}
size_t row_size = cols * sizeof(int);
for(int i=0; i < rows; ++i) {
result[i] = malloc(row_size);
if(result[i] == NULL) {
// could not allocate more memory
// cleanup
return NULL;
}
}
return result;
}
the above implementation have not been tested, but does compile, there are still risk of integer overflow.
Then use the above define function as following:
int **arr = alloc_2d_int_array(ptr->s, ptr->s);
int **B2 = alloc_2d_int_array(ptr->s, ptr->s);
easier implementation (see here(thanks #Lundin))
int **arr = malloc(sizeof(int[ptr->s][ptr->s]);
int **B2 = malloc(sizeof(int[ptr->s][ptr->s]);

How do I correctly assign a struct containing an array of int to an array of struct?

I want to know how to assign a struct containing an array of int to an array of structs. I keep getting the incorrect result no matter what new solution I think of.
I believe the problem lies in this piece of code:
struct Codes *create(int as) {
struct Codes *c = malloc(sizeof (struct Codes)+as * sizeof (int));
c->as = as;
for (int i = 0; i < as; i++) {
c->a[i] = i;
}
return c;
}
The whole code:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
struct Codes {
int as;
int a[];
};
struct Code {
int as;
struct Codes *ci[];
};
struct Codes *create(int as) {
struct Codes *c = malloc(sizeof (struct Codes)+as * sizeof (int));
c->as = as;
for (int i = 0; i < as; i++) {
c->a[i] = i;
}
return c;
}
struct Code *and(int as, struct Codes *cd) {
struct Code *c = malloc(sizeof (struct Code)+as * sizeof (struct Codes));
for (int i = 0; i < as; i++) {
c->ci[i] = cd;
}
c->as = as;
return c;
}
int main(int argc, char **argv) {
struct Codes *cd;
cd = create(4);
struct Code *c;
c = and(2, cd);
for (int i = 0; i < c->as; i += 1) {
for (int j=0; j < c->ci[i]->as; j++) {
printf("%d \n", c->ci[i]->a[j]);
}
}
free(cd);
free(c);
}//main
Actual Result:
0
1
2
3
Expected Result:
0
1
2
3
0
1
2
3
struct Code *c = malloc(sizeof (struct Code)+as * sizeof (struct Codes)); is incorrect. The struct Code 's ci is an array of pointers , but you allocated space for an array of structs.
To fix this, either change to sizeof(struct Codes *), or preferably use the pattern of dereferencing the pointer to the type you're allocating space for:
struct Code *c = malloc( sizeof *c + as * sizeof c->ci[0] );
Also, for (int j; should be for (int j = 0; . Your code causes undefined behaviour by using uninitialized value of j, it's just chance that you happened to get the output you did. Using the gcc flag -Wextra would have diagnosed this error.

Pointers to structures and functions

I have a simple structure called entry defined which contains name and age. Given an array of these structures, I want to sort the array based on age.
Below is my attempt at applying this, at the moment I can't even get this to compile. I think my pointer logic is incorrect in both the if statement comparison and the subsequent swapping of the pointers. I've tried various ways to do the same thing, but I'm not getting anywhere. I'm pretty new to C, and I'm still trying to get my head around pointers, so it's probably something basic I'm misunderstanding. Can anybody please explain what I'm doing wrong below?
Any help would be greatly appreciated.
#include <stdio.h>
struct entry {
char name[15];
int age;
};
void entrySort( struct entry *dict);
void entrySort( struct entry *dict){
int i,j; // counters
int ct = 4;
struct entry *tmp; // temporary holder
for( i = 0; i < ct; i++){
for( j = 0; j < ct; j++ ){
if ((*dict[i].age) > (*dict[j].age)){
tmp = (dict + i);
(dict+i) = (dict+j);
(dict+j) = tmp;
}
}
}
int main (void){
int ct = 4, i;
struct entry reg[4] =
{{ "John", 24 },
{ "Alan", 18 },
{ "Jim", 40 },
{ "Sarah",32 }};
entrySort(reg);
for( i = 0; i < ct; i++)
printf("name: %s. Age: %d\n", reg[i].name, reg[i].age);
return 0;
}
You pass an array of struct entry objects as a pointer: struct entry *dict, but you are treating it as it would be an array of pointers to struct entry objects: (*dict[i]).age.
(dict+i) is still just a pointer pointing to the memory where i+1. element is stored, i.e. &dict[i]. To actually access this element at index i, you need to use dereference operator: *(dict + i), which is equal to dict[i].
And also note that your swapping of elements at i and j is wrong. "Temporary holder" tmp should be an object that will temporarily hold data, not just a pointer to memory, that you are going to rewrite, thus declare it as struct entry tmp;:
struct entry tmp;
for( i = 0; i < ct; i++) {
for( j = 0; j < ct; j++ ) {
if ((dict[i].age) > (dict[j].age)) {
tmp = dict[i];
dict[i] = dict[j];
dict[j] = tmp;
}
}
}
By the way in the code you have posted, the ending curly brace (}) of your if is missing.
Try:
#include <stdio.h>
struct entry {
char name[15];
int age;
};
void entrySort( struct entry *dict, int);
void entrySort( struct entry *dict, int ct){
int i,j; // counters
/* int ct = 4; */
struct entry tmp; // temporary holder
for( i = 0; i < ct; i++){
for( j = 0; j < ct; j++ ){
if ((dict[i].age) > (dict[j].age)){ /* no * */
tmp = *(dict + i);
*(dict+i) = *(dict+j);
*(dict+j) = tmp;
}
}
}
int main (void){
int ct = 4, i;
struct entry reg[4] =
{{ "John", 24 },
{ "Alan", 18 },
{ "Jim", 40 },
{ "Sarah",32 }};
entrySort(reg, ct);
for( i = 0; i < ct; i++)
printf("name: %s. Age: %d\n", reg[i].name, reg[i].age);
return 0;
}
For completeness, here's how you'd do it with qsort:
#include <stdlib.h>
int sort_entry(const void *va, const void *vb) {
const struct entry *a = va;
const struct entry *b = vb;
if(a->age < b->age) return -1;
else if(a->age == b->age) return 0;
return 1;
}
...
qsort(reg, ct, sizeof(struct entry), sort_entry);

C and dynamic structure element access

I have this complicated structure thingie:
#include <stdlib.h>
typedef struct {
int x;
int y;
} SUB;
typedef struct {
int a;
SUB *z;
} STRUCT;
#define NUM 5
int main(void)
{
STRUCT *example;
int i;
example = malloc(sizeof(STRUCT));
example->z = malloc(NUM * sizeof(SUB));
for(i = 0; i < NUM; ++i) {
/* how do I access variable in certain struct of array of z's */
}
return 0;
}
example is dynamically allocated structure and z inside the example is dynamically allocated array of SUB structures.
How do I access certain variable in certain element of structure z?
I have been trying something like this: example->z[i].x but it doesnt seem to work.
At the moment I am using this shabby looking workaraound:
SUB *ptr = example->z;
int i;
for(i = 0; i < amount_of_z_structs; ++i) {
/* do something with 'ptr->x' and 'ptr->y' */
ptr += sizeof(SUB);
}
Your problem isn't where you say it is. Your code as posted gives a compile error:
error: request for member ā€˜zā€™ in something not a structure or union
at the line
example.z = malloc(sizeof(STRUCT));
because you meant to write example->z, since example is a pointer to STRUCT, not a STRUCT.
From there on, you can access example->z[i].x exactly as you said. That syntax has always been fine.
For example:
/* your declarations here */
example = malloc(sizeof(STRUCT));
example->z = malloc(NUM * sizeof(SUB));
for(i = 0; i < NUM; ++i) {
example->z[i].x = i;
example->z[i].y = -i;
printf("%d %d\n", example->z[i].x, example->z[i].y);
}
/* output:
0 0
1 -1
2 -2
3 -3
4 -4
*/
When you have pointers pointing to pointers you often end up running into precedence issues. I can't recall if this is one, but you might try (example->b)[i].x.
First of all, your second malloc is wrong; example is a pointer so this:
example.z = malloc(NUM * sizeof(SUB));
should be this:
example->z = malloc(NUM * sizeof(SUB));
Then in your loop you can say things like this:
example->z[i].x = i;
example->z[i].y = i;
You'll also want to have this near the top of your file:
#include <stdlib.h>
Try this:
int my_x = example[3].z[2].x;
The above code will first access the example[3] (the fourth element of the example array).
Once you get that particular element, its contents can be automatically access in the same way as you do with normal objects.
You then access z[2] from that element. Note that, example[3] is an element, so you could use a . to access its members; if its an array, you can access it as an array.
So till now, example[3].z[2] is one element of the SUB array inside one element of the example array.
Now you can simply access the member x using the way shown above.
typedef struct {
int x;
int y;
} SUB;
typedef struct {
int a;
SUB *z;
} STRUCT;
STRUCT *example;
int main() {
example = malloc(sizeof(STRUCT)*10); //array of 10;
int i=0,j=0;
for (;i<10;i++){
example[i].a = i;
example[i].z = malloc(sizeof(SUB)*5);
for (j=0; j<5; j++)
example[i].z[j].x = example[i].z[j].y = j;
}
//access example[3] and access z[2] inside it. And finally access 'x'
int my_x = example[3].z[2].x;
printf("%d",my_x);
for (i=0;i<10;i++){
printf("%d |\n",example[i].a);
//example[i].z = malloc(sizeof(SUB)*5);
for (j=0; j<5; j++)
printf("%d %d\n",example[i].z[j].x,example[i].z[j].y);
free(example[i].z);
}
free(example);
}
In the 'shabby workaround', you wrote:
SUB *ptr = example->z;
int i;
for(i = 0; i < amount_of_z_structs; ++i) {
/* do something with 'ptr->x' and 'ptr->y' */
ptr += sizeof(SUB);
}
The problem here is that C scales pointers by the size of the object pointed to, so when you add 1 to a SUB pointer, the value is advanced by sizeof(SUB). So, you simply need:
SUB *ptr = example->z;
int i;
for (i = 0; i < NUM; ++i) {
ptr->x = ptr->y = 0;
ptr++;
}
Of course, as others have said, you can also do (assuming C99):
for (int i = 0; i < NUM; ++i)
example->z[i].x = example->z[i].y = 0;
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#define NUM 5
typedef struct
{
int x;
int y;
}SUB;
typedef struct
{
int a;
SUB* z;
}STRUCT;
void main(void)
{
clrscr();
printf("Sample problem..\n\n");
STRUCT* example;
int i;
example = (STRUCT*)malloc(sizeof(STRUCT));
example->z = (SUB*)malloc(NUM * sizeof(SUB));
for(i = 0; i < NUM; i++)
{
example->z[i].x = i +1;
example->z[i].y = (example->z[i].x)+1;
printf("i = %d: x:%d y:%d\n", i, example->z[i].x, example->z[i].y);
}
}

Resources