Contiguous memory for multidimensional array - c

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

Related

segmentation fault on simple loop

I'm trying to write a program that calculates the number of elements of given matrix,for example M[2][3] = [1,2,3][3,4,5]
should give the number of elements from 0 trough 9 in a nxm array.
The algorithm is correct up until line 34(M[i][j] = i + 2;) in which I'm having a segmentation fault.
What am I doing wrong?
#include<stdio.h>
#include<stdlib.h>
#define ROW 10
#define COL 10
#define MAX 10
void Print_Matrix(int **M,int row,int col);
int MallocX(int **M,int row,int col);
int main(void)
{
int **M = 0x0;
int count[MAX] = {0};
int i,j;
if(MallocX(M,ROW,COL)){
fprintf(stdout,"Could not allocate memory\n");
exit(1);
}
for(i = 0;i<ROW;i++){
for(j = 0;j<COL;j++){
M[i][j] = i + 2;
}
}
Print_Matrix(M,ROW,COL);
for(i = 0;i<ROW;i++){
for(j = 0;j<COL;j++){
++count[M[i][j]];
}
}
for(j = 0;j<MAX;j++){
if(count[j]){
printf("%d %d\n",j,count[j]);
}
}
for(i = 0;i<ROW;i++){
free(M[i]);
}
free(M);
}
int MallocX(int **M,int row,int col)
{
int i;
M = (int **) malloc(row * sizeof(int *));
if(M == NULL){
fprintf(stderr,"Error allocating memory\n");
free(M);
return 1;
}
for(i = 0;i<row;i++){
M[i] = (int *) malloc(col * sizeof(int));
if(M[i] == NULL){
fprintf(stderr,"Error allocating memory\n");
free(M[i]);
return 1;
}
}
return 0;
}
void Print_Matrix(int **M,int row,int col)
{
int i,j;
for(i = 0;i<row;i++){
for(j = 0;j<col;j++){
printf("%d ",M[i][j]);
}
printf("\n");
}
}
This is because you are passing M by value, not reference. Your MallocX allocates memory for your matrix, but those allocations are orphaned when you return to the main program, where M is still 0x0 (or NULL), which is why allocation functions typically return a pointer. Perhaps you want something like this:
int **MallocX(int row,int col)
{
int **Matrix, i;
Matrix = malloc(row * sizeof(int*));
if(Matrix == NULL) {
fprintf(stderr,"Error allocating memory\n");
return NULL;
}
for (i = 0; i < row; i++) {
Matrix[i] = (int*) malloc(col * sizeof(int));
if(Matrix[i] == NULL){
fprintf(stderr,"Error allocating memory (%d)\n",i);
for (int j = 0; j < i; ++j)
free(Matrix[j]);
free(Matrix);
return NULL;
}
}
return Matrix;
}
Then in main, call it with:
if (!(M = MallocX(ROW,COL)) {
fprintf(stdout,"Could not allocate memory\n");
exit(1);
}
Note that in your original code, you were calling free(M) when M was NULL, which will itself cause a segfault. So I've tidied up your garbage collection a bit too.

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

Is it possible to dynamically allocate 2-D array in c with using calloc() once?

All the solutions I have seen online has calloc() function used twice, is it possible to do with only using it once?
The below code is not printing the correct array elements
int **ptr;
//To allocate the memory
ptr=(int **)calloc(n,sizeof(int)*m);
printf("\nEnter the elments: ");
//To access the memory
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
scanf("%d",ptr[i][j]);
}
}
Since C99 you can use pointers to VLAs (Variable Length Arrays):
int n, m;
scanf("%d %d", &n, &m);
int (*ptr)[m] = malloc(sizeof(int [n][m]));
for (i = 0; i < n; i++)
{
for (j = 0; j < m; j++)
{
scanf("%d", &ptr[i][j]); // Notice the address of operator (&) for scanf
}
}
free(ptr); // Call free only once
If it's just about minimising the number of calls to memory allocation functions you can created such a jagged array like this:
#include <stdlib.h>
#include <stdio.h>
int ** alloc_jagged_2d_array_of_int(size_t n, size_t m)
{
int ** result = NULL;
size_t t = 0;
t += n * sizeof *result;
t += n*m * sizeof **result;
result = calloc(1, t);
if (NULL != result)
{
for (size_t i = 0; i < n; ++i)
{
result[i] = ((int*) (result + n)) + i*m;
}
}
return result;
}
Use it like this:
#include <stdlib.h>
#include <stdio.h>
int ** alloc_jagged_2d_array_of_int(size_t, size_t);
int main(void)
{
int result = EXIT_SUCCESS;
int ** p = alloc_jagged_2d_array_of_int(2, 3);
if (NULL == p)
{
perror("alloc_jagged_2d_array_of_int() failed");
result = EXIT_FAILURE;
}
else
{
for (size_t i = 0; i < 2; ++i)
{
for (size_t j = 0; j < 3; ++j)
{
p[i][j] = (int) (i*j);
}
}
}
/* Clean up. */
free(p);
return result;
}

Get value of structure inside a structure array

typedef struct{
int number;
char name[100];
} Apple
typedef struct{
Apple *apple;
int bit[2];
} AppleArray;
int main(){
AppleArray *aArray;
loadApple(&aArray);
}
loadApple(AppleArray **aArray){
*aArray = NULL;
for(i=0; i<100; i++){
*aArray = realloc(*aArray, (i+1) * sizeof(AppleArray));
/*SEGFAULT here*/
aArray[i]->apple = NULL;
for(j=0; j<2; j++){
aArray[i]->apple = realloc(aArray[i]->apple, sizeof(Apple) * (j+1))
}
}
}
I want to have an AppleArray with specific size. Each AppleArray will have two Apple. However, I get segfault when i assign NULL to aArray[i]->apple. What is the problem there?
EDIT :
loadApple(AppleArray **aArray){
*aArray = malloc(100 * sizeof(AppleArray));
for(i=0; i<100; i++){
/*SEGFAULT here*/
aArray[i]->apple = NULL;
for(j=0; j<2; j++){
aArray[i]->apple = realloc(aArray[i]->apple, sizeof(Apple) * (j+1))
}
}
}
You can call realloc() only on an address that was returned to you by an prior memory allocation function like malloc()or calloc() otherwise it gives you Undefined Behavior.
C99 Standard 7.20.3.4-3: The realloc function:
void *realloc(void *ptr, size_t size);
If ptr is a null pointer, the realloc function behaves like the malloc function for the
specified size. Otherwise, if ptr does not match a pointer earlier returned by a memory
management function, or if the space has been deallocated by a call to the free or
realloc function, the behavior is undefined.
Apart from what Als has mentioned above, you are also having an array out-of-bounds read problem as after your loop, i value will be 100 and you are trying to access aArray[100] whereas in your logic (though incorrect) your would have allocated memory only till aArray[99].
Your loadApple function can be rewritten as below:
loadApple(AppleArray **aArray)
{
*aArray = NULL;
*aArray = malloc(100 * sizeof(AppleArray));
//I have shown index as 0 here just as an example.
(*aArray)[0].apple = NULL;
(*aArray)[0].apple = malloc(2 * sizeof(Apple));
}
This code should also give the same behavior which the logic of your code is trying to achieve.
<pre>
#include "stdio.h"
#include "stdlib.h"
#define MAX_SIZE 5
#define NAME_SIZE 100
#define APPLE_NUM 2
typedef struct
{
int number;
char name[NAME_SIZE];
}Apple;
typedef struct
{
Apple* apple;
int bit[2];
}AppleArray;
void printApple(AppleArray** aArray)
{
int i;
for (i = 0; i < MAX_SIZE; ++i)
{
fprintf(stderr, "%4d: bit[0] = %d, bit[1] = %d\n", i, (*aArray + i)->bit[0], (*aArray + i)->bit[1]);
int j;
for (j = 0; j < APPLE_NUM; ++j)
{
fprintf(stderr, "\tapple[%d]: number = %d, name = %s\n",
j,
(*aArray + i)->apple[j].number,
(*aArray + i)->apple[j].name);
}
printf("\n");
}
}
void loadApple(AppleArray **aArray)
{
*aArray = NULL;
int i;
for(i = 0; i < MAX_SIZE; i++)
{
AppleArray* tmp = (AppleArray*)realloc(*aArray, (i+1) * sizeof(AppleArray));
if (tmp != NULL)
{
*aArray = tmp;
}
else
{
//error
free(*aArray);
*aArray = NULL;
exit(0);
}
/*SEGFAULT here*/
//aArray[i]->apple = NULL;
(*aArray + i)->apple = NULL;
(*aArray + i)->bit[0] = i;
(*aArray + i)->bit[1] = i + 1;
/*
int j;
for (j = 0; j < 2; j++)
{
(*aArray + i)->apple = realloc(aArray[i]->apple, sizeof(Apple) * (j+1));
}
*/
(*aArray + i)->apple = (Apple*)realloc(NULL, sizeof(Apple) * APPLE_NUM);
int j;
for (j = 0; j < APPLE_NUM; ++j)
{
(*aArray + i)->apple[j].number = j;
snprintf( (*aArray + i)->apple[j].name, NAME_SIZE, "apple_%d_%d", i, j);
}
}//for
}
void destroyApple(AppleArray* thiz)
{
if (thiz == NULL)
{
return;
}
int i;
for (i = 0; i < MAX_SIZE; ++i)
{
free(thiz[i].apple);
thiz[i].apple = NULL;
}
free(thiz);
}
int main()
{
AppleArray *aArray;
loadApple(&aArray);
printApple(&aArray);
destroyApple(aArray);
return 0;
}

C Programming - Initializing a struct 2D array

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++)
{
/* ... */
}
}

Resources