So I have a code and when I run it, it hangs when I enter a size greater than 3. When it's exactly 3 it runs smoothly. I narrowed down the problem to malloc and free and I don't know what the problem is. I'm new at this so any help is appreciated.
do //repeatedly ask the user to put a number between 3-9
{
printf("Enter the size of the game board between 3-9: ");
scanf("%d", &size);
}while(size<3 || size>9);
if((board = (char***)malloc(sizeof(char**)*size))==NULL)
printf("Memory Allocation failed\n");
for(i=0; i<size; i++)
{
if((board[i] = (char**)malloc(sizeof(char*)*size))==NULL)
printf("Memory Allocation failed\n");
for(j=0; j<size; j++)
{
if((board[i][j] = (char *)malloc(sizeof(char)*4))==NULL)
printf("Memory Allocation failed\n");
strcpy(board[i][j], "Go");
}
}
/*************Some random code ***********/
free(board);
for(i=0;i<size;i++)
{
free(board[i]);
for(j=0;j<size;j++)
free(board[i][j]);
}
The problem is you access board after you freed it. You should release memory in exactly the reverse order that you malloc it.
An alternative approach is that you can allocate all the memory you need in a whole, like
char ***board = NULL;
char **rows = NULL;
char *data = NULL;
if((board = (char***)malloc(sizeof(char**)*size))==NULL)
printf("Memory Allocation failed\n");
if((rows = (char**)malloc(sizeof(char*)*size*size))==NULL)
printf("Memory Allocation failed\n");
if((data = (char *)malloc(sizeof(char)*size*size*4))==NULL)
printf("Memory Allocation failed\n");
for (i = 0; i < size; i++) {
int board_offset = i * size;
board[i] = rows[board_offset];
for (j = 0; j < size; j++) {
int row_offset = board_offset + j;
rows[row_offset] = data[row_offset * 4];
stcpy(data[row_offset * 4], "GO");
}
}
free(board);
free(rows);
free(data);
Related
When ever I tried to allocate memory it failed and I don't really know why? This is my school project in which I have to make a game to board and in board struct I have use double pointer of cell structure for player position and his letter now I can't able to allocate the memory and draw_board function just draws the board.
struct game {
struct player *players[NUM_PLAYERS];
int curr_player_num;
struct board *the_board;
struct letter_list *score_list;
};
struct player {
char *name;
char *color_name;
};
struct cell {
struct player *owner;
int letter;
};
struct board {
struct cell **matrix;
int width;
int height;
};
void init_game() {
struct game info;
int i, j;
printf("\nEnter the size of the board (row col)=> eg (5 5): ");
scanf("%d %d", &info.the_board->height, &info.the_board->width);
info.the_board->matrix = (struct cell **)malloc((info.the_board->height) * sizeof(struct cell *));
if (info.the_board->matrix == NULL) {
printf("out of memory!");
}
for (i = 0; i < info.the_board->height; i++) {
printf("%d", info.the_board->width);
info.the_board->matrix[i] = (struct cell *)malloc((info.the_board->width) * sizeof(struct cell)); // i think there is a error
if (info.the_board->matrix[i] == NULL) {
printf("Out of memeory");
}
}
for (i = 0; i < info.the_board->height; i++) {
for (j = 0; j < info.the_board->width; j++) {
info.the_board->matrix[i][j].owner = (void *)NULL;
info.the_board->matrix[i][j].letter = EOF;
}
}
draw_board(&info); //this will print the board
}
int main() {
init_game();
return 0;
}
The board structure pointed to by info.the_board has not been allocated, nor even initialized, dereferencing this pointer has undefined behavior. Furthermore, you must exit the function when you detect an allocation error, otherwise you will crash in the subsequent code.
int init_game() {
struct game info = { 0 };
int i, j;
info.board = calloc(sizeof(*info.board), 1);
if (info.board == NULL) {
printf("cannot allocate board\n");
return -1;
}
printf("\nEnter the size of the board (row col)=> eg (5 5): ");
scanf("%d %d", &info.the_board->height, &info.the_board->width);
info.the_board->matrix = calloc(info.the_board->height, sizeof(struct cell *));
if (info.the_board->matrix == NULL) {
printf("out of memory!\n");
return -1;
}
for (i = 0; i < info.the_board->height; i++) {
//printf("%d", info.the_board->width); //debug
info.the_board->matrix[i] = calloc(info.the_board->width, sizeof(struct cell));
if (info.the_board->matrix[i] == NULL) {
printf("Out of memory\n");
// free previous matrix rows
while (i --> 0) {
free(info.the_board->matrix[i])
}
return -1;
}
}
for (i = 0; i < info.the_board->height; i++) {
for (j = 0; j < info.the_board->width; j++) {
info.the_board->matrix[i][j].owner = NULL;
info.the_board->matrix[i][j].letter = EOF;
}
}
draw_board(&info); //this will print the board
...
return 0;
}
This is the code for allocating memory for 2 Arrays of uknown size. N is given by the user:
K=malloc(N*sizeof(int));
if(K==NULL){
// printf("Sorry, cannot allocate memory\n");
return -1;
}
for(i = 0;i < N;i++){
C = malloc(N * sizeof(int *));
if (C == NULL){
return -1;
}
for (i = 0 ; i < N ; i++) {
*(C+i) = malloc(K[i] * sizeof(int));
if (*(C+i) == NULL){
return -1; }
}
}
Both arrays are filled with numbers given by the user.
And to free them:
for (i=0 ; i < N ; i++){
for (i=0 ; i < N ; i++){
free(*(C+i));
}
free(C);
}
void free(void*K);
by debugging with gbd i come across this error
Program received signal SIGSEGV, Segmentation fault.
_int_free (av=0x10102464c457f, p=0x8005770, have_lock=) at malloc.c:4304
4304 malloc.c: No such file or directory.
by using valgrind to go deeper into this error it seems, that i have no leaks.What could be the problem?
for(i = 0;i < N;i++){int *));
if (C == NULL){
return -1;
}
with every iteration the previous allocated memory is lost as the pointer is assigned with the reference to the newly allocated memory block.
if your intention was to change the size of the allocated memory you should use realloc instead
Assuming C is int ** (as per you program logic)
C = NULL;
for(i = 0;i < N;i++){
void *tmp = realloc(C, N * sizeof(*C));
if (tmp == NULL){
free(C);
return -1;
}
C = tmp;
}
I believe this code forces memory allocation for a 3-d array to be contiguous.
void ***calloc_3d_array(size_t n3, size_t n2, size_t n1, size_t size){
void ***array;
size_t i, j;
if ((array = (void***)calloc(n3, sizeof(void**))) == NULL) {
printf("[calloc_3d] failed to allocate memory for %d 1st-pointers\n",
(int)n3);
return NULL;
}
if ((array[0] = (void**)calloc(n3*n2, sizeof(void*))) == NULL) {
printf("[calloc_3d] failed to allocate memory for %d 2nd-pointers\n",
(int)(n3*n2));
free((void*)array);
return NULL;
}
for (i=1; i<n3; i++) {
array[i] = (void**)((unsigned char*)array[0]+i*n2*sizeof(void*));
}
if ((array[0][0] = (void*)calloc(n3*n2*n1, size)) == NULL) {
printf("[calloc_3d] failed to alloc. memory (%d X %d X %d of size %d)\n",
(int)n3, (int)n2, (int)n1, (int)size);
free((void*)array[0]);
free((void*)array);
return NULL;
}
for (j=1; j<n2; j++) {
array[0][j] = (void**)((unsigned char*)array[0][j-1]+n1*size);
}
for (i = 1; i < n3; i++) {
array[i][0] = (void**)((unsigned char*)array[i-1][0]+n2*n1*size);
for (j = 1; j < n2; j++) {
array[i][j] = (void**)((unsigned char*)array[i][j-1]+n1*size);
}
}
return array;
}
I am trying to alter this into a function that allocates a 4-d array contiguously. I do not fully understand the 3-d case flawless, so abstracting to a 4th dimension is a little shaky. I mostly unsure exactly why in any loop we have either array[i] = (void**) or array[i][j] = (void**) in the 3d code, so in the 4d code I have all the array[i][j][k] = (void***). Here is what I currently have
void ****calloc_4d_array(size_t n4, size_t n3, size_t n2, size_t n1, size_t size){
void ****array;
size_t i, j, k;
/* Alloc array of 3d pointers */
if ((array = (void****)calloc(n4, sizeof(void***))) == NULL) {
printf("[calloc_3d] failed to allocate memory for %d 1st-pointers\n",
(int)n4);
return NULL;
}
/* In first slot allocate a entire 2d pointer array */
if ((array[0] = (void***)calloc(n4*n3, sizeof(void**))) == NULL) {
printf("[calloc_3d] failed to allocate memory for %d 2nd-pointers\n",
(int)(n4*n3));
free((void*)array);
return NULL;
}
/* Loop over slots and adjust address to accommodate 2d pointers */
for (i = 1; i < n4; i++) {
array[i] = (void***)((unsigned char*)array[0]+i*n3*sizeof(void**));
}
/* In the first 2d pointer, allocate the entire space for 1d pointers*/
if ((array[0][0] = (void**)calloc(n4*n3*n2, sizeof(void*))) == NULL) {
printf("[calloc_3d] failed to allocate memory for %d 3rd-pointers\n",
(int)(n4*n3*n2));
free((void*)array[0]);
free((void*)array);
return NULL;
}
/* Loop over other 2d slots and adjust address to accommodate type */
for (j=1; j<n3; j++) {
array[0][j] = (void**)((unsigned char*)array[0][j-1]+n2*size);
}
for (i=1; i<n4; i++) {
array[i][0] = (void**)((unsigned char*)array[i-1][0]+n3*n2*size);
for (j=1; j<n3; j++) {
array[i][j] = (void**)((unsigned char*)array[i][j-1]+n2*size);
}
}
/* Finally allocate for entire array */
if ((array[0][0][0] = (void*)calloc(n4*n3*n2*n1, size)) == NULL) {
printf("[calloc_3d] failed to alloc. memory (%d X %d X %d X %d of size %d)\n",
(int)n4, (int)n3, (int)n2, (int) n1, (int)size);
free((void*)array[0][0]);
free((void*)array[0]);
free((void*)array);
return NULL;
}
for (k=1; k<n2; k++) {
array[0][0][k] = (void***)((unsigned char*)array[0][0][k-1]+n1*size);
}
for (j=1; j<n3; j++) {
array[0][j][0] = (void***)((unsigned char*)array[0][j-1][0]+n2*n1*size);
for (k=1; k<n2; k++) {
array[0][j][k] = (void***)((unsigned char*)array[0][j][k-1]+n1*size);
}
}
for(i=1; i<n4; i++) {
array[i][0][0] = (void***)((unsigned char*)array[i-1][0][0]+n3*n2*n1*size);
for (j=1; j<n3; j++) {
array[i][j][0] = (void***)((unsigned char*)array[i][j-1][0]+n2*n1*size);
for (k=1; k<n2; k++) {
array[i][j][k] = (void***)((unsigned char*)array[i][j][k-1]+n1*size);
}
}
}
return array;
}
Edit: The compiler gave me a warning relating to my (void***) question, and it seems to make sense that array[][] is a (void**), but I still don't know why it is happy with array[i] = (void***) instead of array[i] = (void*). Otherwise said, why is it (void*) with calloc array[0][0][0] = (void*)calloc(n4*n3*n2*n1, size), but (void***) when using the bit shifting/setting the address(?) array[0][0][k] = (void***)((unsigned char*)array[0][0][k-1]+n1*size);? I would think whatever kind of object array[][][] is either (void*) or (void***).
This should allocate 2 and above dimensions array continuously use recursion. Suggest use FORTRAN for such kind of high dimensional computation, this is not memory efficient. The example seems valgrind clean.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
void *alloc_nd(int *dim, int nd, size_t size)
{
assert(nd>=2);
void **p = malloc(sizeof(void*)*dim[0]);
if(nd==2) {
p[0] = malloc(size*dim[0]*dim[1]);
for(int i=1; i<dim[0]; i++)
p[i] = p[i-1]+size*dim[1];
} else {
int xd[nd-1];
for(int i=1; i<nd; i++)
xd[i-1] = dim[i];
xd[0] *= dim[0]; //callapse the 1st two dimension
p[0] = alloc_nd(xd, nd-1, size);
for(int i=1; i<dim[0]; i++)
p[i] = p[i-1]+sizeof(void*)*dim[1];
}
return p;
}
void free_nd(void *p, int nd)
{
if(nd==2) {
free(((void**)p)[0]);
free(p);
} else {
free_nd(((void**)p)[0], nd-1);
free(p);
}
}
int main()
{
int dim[] = {3,4,5,6};
int ****array;
array = (int****)alloc_nd(dim, 4, sizeof(int));
for(int i0=0; i0<dim[0]; i0++)
for(int i1=0; i1<dim[1]; i1++)
for(int i2=0; i2<dim[2]; i2++)
for(int i3=0; i3<dim[3]; i3++)
array[i0][i1][i2][i3] = i0+i1+i2+i3;
int *p = &array[0][0][0][0]; //do you mean continuous in this way?
for(int i=0; i<dim[0]*dim[1]*dim[2]*dim[3]; i++)
printf("p[%5d]=%d\n", i, p[i]);
free_nd(array, 4);
return 0;
}
Okay so I'm trying to pass elements of a 2D array with string elements to a 2D array in struct. I made a code, but it receives a run-time error. I think there's a problem in the code where I'm trying to initialize board2[i][j]. Any help is appreciated.
char ***board;
int i, j, size;
printf("Enter the size of array:");
scanf("%d", &size);
if((board = (char***)malloc(sizeof(char**)*size))==NULL)
{
printf("Memory Allocation failed\n");
return -1;
}
for(i=0; i<size; i++)
{
if((board[i] = (char**)malloc(sizeof(char*)*size))==NULL)
{
printf("Memory Allocation failed\n");
return -1;
}
for(j=0; j<size; j++)
{
if((board[i][j] = (char *)malloc(sizeof(char)*4))==NULL)
{
printf("Memory Allocation failed\n");
return -1;
}
a = rand() % 2;
b = rand() % 2;
if(a==0 && b==0)
strcpy(board[i][j], "ab");
else if(a && b==0)
strcpy(board[i][j], "Ab");
else if(a==0 && b==1)
strcpy(board[i][j], "aB");
else
strcpy(board[i][j], "AB");
}
struct data{
const char *element;
int visited;
};
void board2_initialize(char ***board, int size)
{
struct data **board2;
for(i=0;i<size;i++)
{
for(j=0;j<size;j++)
{
board2[i][j].element = board[i][j];
board2[i][j].visited = 0;
printf("%s", board2[i][j].element);
}
}
}
EDIT: Forgot to mention that the initialization will occur inside a function
You allocate it just the same way you do the board arrays:
struct data **board2 = malloc(sizeof(struct data *) * size);
for(i = 0; i < size; i++)
{
board2[i] = malloc(sizeof(struct data) * size);
for(j = 0; j < size; j++)
{
/* ... */
}
}
I have a quadratic matrix(two-dimensional dynamic array of pointers) and need to change rows/columns order. The matrix is very big that's why I have decided just to change pointers instead of copying all of elements. I also have another array which specifies a computation.
Rows permutation specifies this way:
4,3,2,1 - it means that the first row must be on the fourth place, the second row must be on the third place, etc.
The same situation is with the columns.
How to implement such algorithm of changing of rows order(permutation of of pointers)? Here it is my version, but it doesn't work. I want to copy pointers but element is copied instead of it and then appears a segmentation fault.
When I add '&' to get address, the compiler says that it is a syntax error:
orderOfRows[i] = &auxMatrix[computation[i]];
Here it is my code:
static int N = 6;
static int **orderOfRows;
int **sourceMatrix;
int **auxMatrix;
int main() {
int* computation = (int*)malloc(N*sizeof(int));
computation[0] = 1;
computation[1] = 6;
computation[2] = 3;
computation[3] = 7;
computation[4] = 4;
computation[5] = 2;
}
printf("After computation has been done: \n");
changeRowOrder(computation);
void changeRowOrder(int *computation) {
int i;
// change rows order and dopy them into a temp array
for(i = 0; i < N; ++i) {
// static arrays
orderOfRows[i] = auxMatrix[computation[i]];
}
// recover matrix
for(i = 0; i < N; ++i) {
auxMatrix[i] = orderOfRows[i];
}
void allocate2dMemory() {
int i = 0;
sourceMatrix = (int**)malloc(N * sizeof(int *));
if(sourceMatrix == NULL) {
fprintf(stderr, "out of memory\n");
exit(2);
}
for(i = 0; i < N; i++) {
sourceMatrix[i] = (int*)malloc(N * sizeof(int));
if(sourceMatrix[i] == NULL) {
fprintf(stderr, "out of memory\n");
exit(2);
}
}
auxMatrix = (int**)malloc(N * sizeof(int *));
if(auxMatrix == NULL) {
fprintf(stderr, "out of memory\n");
exit(2);
}
for(i = 0; i < N; i++) {
auxMatrix[i] = (int*)malloc(N * sizeof(int));
if(auxMatrix[i] == NULL) {
fprintf(stderr, "out of memory\n");
exit(2);
}
}
orderOfRows = (int**)malloc(N * sizeof(int *));
if(orderOfRows == NULL) {
fprintf(stderr, "out of memory\n");
exit(2);
}
for(i = 0; i < N; i++) {
orderOfRows[i] = (int*)malloc(N * sizeof(int));
if(orderOfRows[i] == NULL) {
fprintf(stderr, "out of memory\n");
exit(2);
}
}
}
}
I will spend 2*N(copy pointers and then recover) operations instead of N*N.
And I have another question: how I can do the permutation of columns using this idea? If it isn't possible how can I do the permutation of columns but not to copy all elements of the matrix? The programming language is only C.
Instead of
orderOfRows[i] = &auxMatrix[computation[i]];
you should have
for (int j = 0; j < N; ++j)
{
orderOfRows[i][j] = auxMatrix[computation[i]][j];
}
And one more thing:
if you havecomputation[1] = 6, it means that by doing auxMatrix[computation[i]] you try to access auxMatrix[6], which you can't do because auxMatrix's size is 6x6.
If you want to be able to swap both rows and columns without copying, you are going to need to have two auxiliary indices:
int *row_index;
int *col_index;
and access the elements of your matrix using these:
element = matrix[row_index[row]][col_index[col]];
To swap a row or column, you simply swap the corresponding elements of row_index or col_index.