Memory allocation in my simple game [duplicate] - c

This question already has answers here:
Using malloc for allocation of multi-dimensional arrays with different row lengths
(8 answers)
Closed 9 years ago.
I'm writing the minesweeper game in C. I want be able to play games with different minefields with different sizes and number of mines
I've created such structures to describe my data:
typedef struct t_Place Place;
struct t_Place{
unsigned numberOfMinesNear;
int mine;
int state;
};
typedef struct t_Minefield Minefield;
struct t_Minefield{
int xSize;
int ySize;
unsigned minesNumber;
Place **places;
};
So, now I'm trying to initialize my minefield. I do the following:
void makeGame(Minefield *minefield, unsigned x, unsigned y, unsigned mines){
int i, j;
minefield->places = malloc(x * y * sizeof(Place));
for(i = 0; i < x; i++)
for(j = 0; j < y; j++){
minefield->places[i][j].mine = EMPTY;
minefield->places[i][j].state = HIDDEN;
minefield->places[i][j].numberOfMinesNear = 0;
}
minefield->xSize = x;
minefield->ySize = y;
unsigned minesToPlace = mines;
srand(time(NULL));
while(minesToPlace > 0){
i = rand() % x;
j = rand() % y;
if(minefield->places[i][j].mine)
continue;
minefield->places[i][j].mine = MINE;
minesToPlace--;
}
minefield->minesNumber = mines;
// here will be call of play(minefield) function to start the game
}
int main(){
Minefield *gameField = (Minefield *) malloc(sizeof(Minefield));
makeGame(gameField, DEFAULT_X, DEFAULT_Y, DEFAULT_MINES);
// DEFAULT_X = DEFAULT_Y = DEFAULT_MINES = 10
free(gameField);
return 0;
}
I'm getting segfault at first line of code in makeGame function. What i'm doing wrong? I want allocate memory for my minefield dynamically, not statically.

minefield->places = malloc(x * y * sizeof(Place));
The above memory allocation might be the source of the problem , places is a two star pointer , so there must be two malloc() calls , one to allocate the row number **place pointers , and then another malloc() , to allocate column number of *place pointers of type place.
Here is a SSCCE of allocating/initializing a two star pointer contained inside a structure.
#include <stdio.h>
#include <stdlib.h>
#define ROW_SZ 5
#define COL_SZ 25
typedef struct demo{
char **str;
}demo;
int main()
{
demo *d = malloc( sizeof(demo) );
d->str = malloc(ROW_SZ * sizeof(char*) ); //d->str is assigned char**
for ( i = 0; i < ROW_SZ; i++ )
d->str[i] = malloc(COL_SZ * sizeof(char) ); //d-str[i] is assigned char*
// code here to use d->str[ROW_SZ][COL_SZ]
for ( i = 0; i < ROW_SZ; i++ )
free(d->str[i]);
free(d->str);
free(d);
return 0;
}

This is how I usually see 2D arrays allocated:
minefield->places = malloc(x * sizeof(Place *));
for(i = 0; i < x; i++)
{
minefield->places[i] = malloc(x * sizeof(Place));
}
Try this and see if it makes you segfault vanish.

Related

Malloc and Realloc for Int Array [duplicate]

This question already has answers here:
How to find the size of an array (from a pointer pointing to the first element array)?
(17 answers)
Closed 3 months ago.
I've just started learning malloc() and realloc() and when testing them, I came across this issue with reallocating the size of an int array.
the program is supposed to make an array, initially of size two, but it's supposed to increase its size and add values to it ten times. However it doesn't increase its size and the output ends up being array = {0,1} when it should be array = {0,1,2,3,4,5,6,7,8,9}
#include <stdlib.h>
#include <stdio.h>
int main(void) {
int *array= malloc(sizeof(int)*2);
for (int x = 0; x < 10; x++) {
array = realloc(array, sizeof(int)*(2+x));
array[x] = x;
}
for (int i = 0; i<(sizeof(array)/sizeof(array[0])); i++) {
printf("%d\n",array[i]);
}
free(array);
}
could someone explain why it doesn't work?? I've tried looking for answers but none of this makes sense to me lol.
The expression
sizeof(array)/sizeof(array[0])
is equivalent to
sizeof( int * )/sizeof( int )
and yields either 2 or 1 depending on the used system.
Also the expression (2+x) in this statement
array = realloc(array, sizeof(int)*(2+x));
used in each iteration of the for loop does not make sense.
It seems you mean something like the following
enum { N = 10 };
size_t n = 2;
int *array = malloc( n * sizeof( int ) );
for ( int x = 0; x < N; x++ ) {
if ( n <= x )
{
n += 2;
array = realloc( array, n * sizeof( int ) );
}
array[x] = x;
}
for ( int i = 0; i < N; i++ ) {
printf("%d\n",array[i]);
}
free(array);
In general it is safer to use an intermediate pointer in the call pf realloc like for example
int *tmp = realloc( array, n * sizeof( int ) );
if ( tmp != NULL ) array = tmp;
Otherwise you can loose the allocated memory if the call of realloc will return a null pointer.
The problem is that sizeof(array) will just return the size of the pointer (8 bytes on a 64-bit system). You need to track the array size in another variable. For example...
#include <stdlib.h>
#include <stdio.h>
int main(void) {
int *array= malloc(sizeof(int));
int size;
for (size = 0; size < 10; size++) {
array = realloc(array, sizeof(int)*(1+size));
array[size] = size;
}
for (int i = 0; i<size; i++) {
printf("%d\n",array[i]);
}
printf("array size: %ld\n",size*sizeof(int));
free(array);
}

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.

What is the correct way to allocate this nested structures?

I'm having some trouble trying to figure out how to allocate and free the memory for this structures.
I need to use this to create FiniteTable's to use in Newton Interpolation.
typedef struct{
unsigned int empty;
float value;
}FiniteTableValue;
The fist one is kind of a Node that has the real value.
typedef struct{
FiniteTableValue *column;
unsigned int length;
}FiniteTableRow;
FiniteTableRow keeps an array of FiniteTableValues.
typedef struct{
FiniteTableRow *row;
unsigned int length;
}FiniteTable;
FiniteTable then keeps an array of FiniteTableRows.
typedef struct{
FiniteTable *tables;
unsigned int length;
}FiniteTableList;
FiniteTableList is the list of FiniteTable's
I tried to debugg it with valgrind and it seems I always access some address that I didn't allocate.
Also, is this the right way to deallocate all ?
FiniteTableList *ftl ...
...
for(int i = 0; i < ftl->length; i++){
FiniteTable table = ftl->tables[i];
for(int j = 0; j < table.length; j++){
FiniteTableRow row = table.row[j];
free(row.column);
}
free(table.row);
}
free(ftl->tables);
free(ftl);
In your deallocation example the Ftl object is a FiniteTableList rather than a pointer (FiniteTableList *). I think you meant to write:
FiniteTableList ftl ...
To allocate memory for a FiniteTableList structure you'd do something like this:
/* Assuming every table in the list will have num_rows rows and num_columns columns. */
FiniteTableList *
allocate_table_list (int num_rows, num_columns, int num_tables)
{
FiniteTableList * res = malloc (sizeof *res);
res->tables = malloc (num_tables * sizeof (*res->tables));
res->length = num_tables;
for (int t = 0; t < num_tables; t++)
{
FiniteTable table = res->tables[t];
table.row = malloc (num_rows * sizeof (*table.row));
table.length = num_rows;
for (int r = 0; r < num_rows; r++)
{
FiniteTableRow row = table.row[r];
row.column = malloc (num_columns * sizeof (*row.column));
row.length = num_columns;
}
}
return res;
}
If you want to zero-initialise the memory you allocate you can substitute the calls to malloc by calloc

Passing an element of a generic array to a generic function

We have an array with pointers to generic arrays, and an array of generic functions, we want to apply to each element in array i the function i from func_ptarrs.
typedef struct genarr{
void * arr;
int elemsize;
int numelem;
}GENARR;
typedef void(*funcptr)(void*);
typedef unsigned char byte;
void updateall(GENARR *arrs, funcptr *func_ptarrs, int n){
int j,i;
for (i = 0; i < n; i++){
for (j = 0; j < arrs[i].numelem; j++){
func_ptarrs[i]((arrs[i].((byte*)(arr + j*arrs[i].elemsize)))); //error: expected member name
//func_ptarrs[i]((arrs[i].arr)); //no error
}
}
}
In the second try it's pointer to the beginning of the array so it's accepted, but I need to be able to send each element of the array to the generic function.
I don't understand how to send the right amount of bytes and move correctly in array all while sending pointers of the elements to the generic functions.
Maybe I should use memcpy?
You need this instead,
func_ptarrs[i](((byte*) arrs[i].arr + j * arrs[i].elemsize))
and I think it's pretty obvious why it would work.
You could write accessor macros too, like
#define ARRAY_VALUE(type, x, i (*(type *) ((x).arr + (i) * (x).elemsize))
which you can then use like
#include <stdio.h>
#include <stdlib.h>
#define ARRAY_VALUE(type, x, i) (*(type *) ((x).arr + (i) * (x).elemsize))
typedef struct genarr
{
void * arr;
int elemsize;
int numelem;
} GENARR;
int main (void)
{
GENARR array;
int data[10];
array.arr = data;
array.elemsize = sizeof(*data);
array.numelem = sizeof(data) / array.elemsize;
for (int i = 0 ; i < array.numelem ; ++i)
ARRAY_VALUE(int, array, i) = i;
for (int i = 0 ; i < array.numelem ; ++i)
printf("%d\n", ARRAY_VALUE(int, array, i));
return 0;
}

Dynamic array in struct calloc or pointers failing, 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)

Resources