Free dynamically created 3d array in C - c

None of the answers I have found seem to address my issue. I am creating a dynamic 3d array in C and later freeing it. I can store and later access the data stored in this array using a nested for loop but I get an access violation when trying to free it using the same nested for loop setup. Where am I going wrong?
unsigned char ***buff1;
int r, c;
someFunction(&buff1, &r, &c);
for(int i = 0; i < r; ++i)
{
for(int j = 0; j < c; ++j)
{
free(buff1[i][j]);
}
free(buff1[i]);
}
free(buff1);
someFunction(unsigned char**** buff, int *nR, int *nC)
{
...
*buff = (SQLCHAR***)malloc(*nR * sizeof(SQLCHAR**));
for(int i = 0; i < *nR; ++i)
{
(*buff)[i] = (SQLCHAR**)malloc(*nC * sizeof(SQLCHAR**));
for(int j = 0; j < *nC; ++j)
{
(*buff)[i][j] = (SQLCHAR*)malloc(256);
}
}
}

Multiple things are wrong:
unsigned char**** buff
What is this, if not wrong? (Well, OK, not technically, but stylistically anyway...)
(SQLCHAR*)malloc(256);
isn't any better either, since you must not cast the return value of malloc() in C.
The third mistake is that you don't have a 3D array. You have a pointer-to-pointer-to-pointer. Ewww. Ugly. Why not allocate a true 3D array instead?
size_t xsize, ysize, zsize; // initialize these!
unsigned char (*arr)[ysize][zsize] = malloc(sizeof(*arr) * xsize);
Then all you need to do in order to free it is:
free(arr);
Honestly, isn't this way better?

I try you code in this way,and it works good:
#include "stdio.h"
#include "stdlib.h"
int someFunction (unsigned char**** buff, int *nR, int *nC)
{
int i,j;
*buff = (unsigned char ***)malloc(*nR * sizeof(char**));
for(i = 0; i < *nR; ++i)
{
(*buff)[i] = (unsigned char**)malloc(*nC * sizeof(char**));
for(j = 0; j < *nC; ++j)
{
(*buff)[i][j] = (unsigned char*)malloc(256);
(*buff)[i][j][0] ='1';
}
}
}
int main()
{
unsigned char ***buff1;
int r = 3, c= 2,i,j;
someFunction(&buff1, &r, &c);
for( i = 0; i < r; ++i)
{
for(j = 0; j < c; ++j)
{
printf(" %c",buff1[i][j][0]);
free(buff1[i][j]);
}
free(buff1[i]);
}
free(buff1);
}
So, maybe the mistake is not happening in the code you are showing to us.

Your code looks pretty buggy. For starters you are calling someFunction(&buff1, &r, &c) while that function expects ints and not int *s. Later you dereference nR and nC and they aren't pointers.
I guess you should be getting some nasty warnings when compiling.

Related

C allocate 'array pointer' inside a function

Related to dynamic allocation inside a function, most questions & answers are based on double pointers.
But I was recommended to avoid using double pointer unless I have to, so I want to allocate a 'array pointer' (not 'array of pointer') and hide it inside a function.
int (*arr1d) = calloc(dim1, sizeof(*arr1d));
int (*arr2d)[dim2] = calloc(dim1, sizeof(*arr2d));
Since the above lines are the typical dynamic-allocation of pointer of array, I tried the following.
#include <stdio.h>
#include <stdlib.h>
int allocateArray1D(int n, int **arr) {
*arr = calloc(n, sizeof(*arr));
for (int i = 0; i < n; i++) {
(*arr)[i] = i;
}
return 0;
}
int allocateArray2D(int nx, int ny, int *(*arr)[ny]) {
*arr[ny] = calloc(nx, sizeof(*arr));
for (int i = 0; i < nx; i++) {
for (int j = 0; j < ny; j++) {
(*arr)[i][j] = 10 * i + j;
}
}
return 0;
}
int main() {
int nx = 3;
int ny = 2;
int *arr1d = NULL; // (1)
allocateArray1D(nx, &arr1d);
int(*arr2d)[ny] = NULL; // (2)
allocateArray2D(nx, ny, &arr2d);
for (int i = 0; i < nx; i++) {
printf("arr1d[%d] = %d \n", i, arr1d[i]);
}
printf("\n");
printf("arr2d \n");
for (int i = 0; i < nx; i++) {
for (int j = 0; j < ny; j++) {
printf(" %d ", arr2d[i][j]);
}
printf("\n");
}
return 0;
}
And the error message already comes during the compilation.
03.c(32): warning #167: argument of type "int (**)[ny]" is incompatible with parameter of type "int *(*)[*]"
allocateArray2D(nx, ny, &arr2d);
^
It is evident from the error message that it has been messed up with the argument types (that I wrote as int *(*arr)[ny]) but what should I have to put there? I tried some variants like int *((*arr)[ny]), but didn't work).
And if I remove the 2D parts, then the code well compiles, and run as expected. But I wonder if this is the right practice, at least for 1D case since there are many examples where the code behaves as expected, but in fact there were wrong or un-standard lines.
Also, the above code is not satisfactory in the first place. I want to even remove the lines in main() that I marked as (1) and (2).
So in the end I want a code something like this, but all with the 'array pointers'.
int **arr2d;
allocateArray2D(nx, ny, arr2d);
How could this be done?
You need to pass the array pointer by reference (not pass an array pointer to an array of int*):
int *(*arr)[ny] -> int (**arr)[ny]
The function becomes:
int allocateArray2D(int nx, int ny, int (**arr)[ny]) {
*arr = calloc(nx, sizeof(int[ny])); // or sizeof(**arr)
for (int i = 0; i < nx; i++) {
for (int j = 0; j < ny; j++) {
(*arr)[i][j] = 10 * i + j;
}
}
return 0;
}
For details, check out Correctly allocating multi-dimensional arrays
Best practices with malloc family is to always check if allocation succeeded and always free() at the end of the program.
As a micro-optimization, I'd rather recommend to use *arr = malloc( sizeof(int[nx][ny]) );, since calloc just creates pointless overhead bloat in the form of zero initialization. There's no use of it here since every item is assigned explicitly anyway.
Wrong parameter type
Strange allocation
Wrong size type
I would return the array as void * too (at least to check if allocation did not fail).
void *allocateArray2D(size_t nx, size_t ny, int (**arr)[ny]) {
//*arr = calloc(nx, sizeof(**arr)); calloc is not needed here as you assign values to the array
*arr = malloc(nx * sizeof(**arr));
for (size_t i = 0; i < nx; i++) {
for (size_t j = 0; j < ny; j++) {
(*arr)[i][j] = 10 * i + j;
}
}
return *arr;
}

How to return an array of char pointers? What is wrong in my code?

I have seen similar posts related to my question but I could not find any answer to understand the bug in this code.
So, I have a function whose return type can't be changed (for case 1). For case 2, I would like to know how to return char *a[];
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char **myfunc(int n) {
char **a = malloc(n * sizeof(char *));
int i, j = 1;
for (i = 0; i < n; i++)
a[i] = malloc(9 * sizeof(char));
for (i = 0; i < n; i++) {
snprintf(a[i], 5, "%d", i);
return a;
}
int main() {
int num = 10, i;
char **ar = myfunc(num);
for (i = 0; i < num; i++)
printf("%s\n", ar[i]);
return 0;
}
1) In the myfunc(), how should I return a correctly? My compiler is throwing me a warning that return from incompatible pointer type.
2) In case, if I change my above myfunc() as follows, how should I return the modified buffer?
char ???myfunc(int n) {
char *a[n];
for (i = 0; i < n; i++)
a[i] = malloc(10 * sizeof(char));
return ?
}
3) In both cases, how should I handle the return inside the main() function?
Case 2:
char *myfunc(int n) {
static char *a[n];
int i;
for (i = 0; i < n; i++)
a[i] = malloc(9 * sizeof(char));
for (i = 0; i < n; i++)
snprintf(a[i], 5, "%d", i);
return a;
}
int main() {
int num = 10, i;
char *ar = myfunc(num);
for (i = 0; i < num; i++)
printf("%s\n", ar[i]);
return 0;
}
Your code was mis-indented, which makes it hard to read and hides silly mistakes such as the extra brace after the second for.
Once corrected for this mistake, the code compiles and runs fine:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char **myfunc(int n) {
char **a = malloc(n * sizeof(char *));
int i;
for (i = 0; i < n; i++)
a[i] = malloc(9 * sizeof(char));
for (i = 0; i < n; i++)
snprintf(a[i], 9, "%d", i);
return a;
}
int main() {
int num = 10, i;
char **ar = myfunc(num);
for (i = 0; i < num; i++)
printf("%s\n", ar[i]);
return 0;
}
If you change myfunc() to define a as char *a[n];, you have a major problem when returning a from myfunc() as the array is defined only inside the scope of myfunc(). Returning its address, which is simply return a; will cause undefined behavior in main() because the space it points to might have been reused for other stuff, such as printf() local variables.
The third option where you define a as static char *a[n]; does not compile because the size of static objects must be known at compile time. Using local static objects is not advisable as it makes the program harder to understand and non-reentrant, with hidden internal state, etc. One such function is strtok() from <string.h>.

2D arrays using arrays of pointers or pointers to pointers in C?

I'm writing a C for which I need to create a 2D array. I've found a solution to my problem using double pointers (pointers to pointers) in the following way:
#include <stdio.h>
#include <stdlib.h>
int d = 3;
#define DIM_MAX 9
void changeArray(int d, int *array[d]);
int main()
{
//alocate array of 'd' colummns and 'd' row using malloc using array of pointers
int **array = malloc(d*sizeof(int *));
for(int count = 0; count < d; count++)
{
array[count] = malloc(d*sizeof(int *));
}
/* Call changeArray function */
changeArray(d, array);
for(int i = 0; i < d; i++)
{
for(int j = 0; j < d; j++)
{
printf("%d ", array[i][j]);
}
printf("\n");
}
for(int count = 0; count < d; count++)
{
free(array[count]);
}
return 0;
}
void changeArray(int n, int *array[d])
{
for(int i =0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
array[i][j] = i*j;
}
}
return;
}
The code above works pretty well (it seems), but I've read in the web that using pointer to pointer is not the correct way to create 2D arrays. So I've come up with the following code, which also works:
#include <stdio.h>
#include <stdlib.h>
#define DIM_MAX 9
int d = 3;
void changeArray(int d, int *array[d]);
int main()
{
//alocate array of 'd' colummns and 'd' row using malloc using array of pointers
int *array[DIM_MAX] = {0};
for(int count = 0; count < d; count++)
{
array[count] = (int *)malloc(d*sizeof(int *));
}
/* Call changeArray function */
changeArray(d, array);
for(int i = 0; i < d; i++)
{
for(int j = 0; j < d; j++)
{
printf("%d ", array[i][j]);
}
printf("\n");
}
for(int count = 0; count < d; count++)
{
free(array[count]);
}
return 0;
}
void changeArray(int n, int *array[d])
{
for(int i =0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
array[i][j] = i*j;
}
}
return;
}
What is the difference in using any of the two ways above to write this code?
[Not an answer, but an alternative approach to achieve the desired result, namely defining a user-defined 2D array.]
Assuming the compiler in use supports VLAs you could do this:
#include <stddef.h> /* for size_t */
void init_a(size_t x, size_t y, int a[x][y]); /* Order matters here!
1st give the dimensions, then the array. */
{
for (size_t i = 0; i < x; ++i)
{
for (size_t j = 0; j < y; ++j)
{
a[i][j] = (int) (i * j); /* or whatever values you need ... */
}
}
}
int main(void)
{
size_t x, y;
/* Read in x and y from where ever ... */
{
int a[x][y]; /* Define array of user specified size. */
init_a(x, y, a); /* "Initialise" the array's elements. */
...
}
}
It is actually pretty simple. All you have to do is this:
int i[][];
You are overthinking it. Same as a normal array, but has two indexes.
Let's say you want to create a "table" of 4 x 4. You will need to malloc space for 4 pointers, first. Each of those index points will contain a pointer which references the location in memory where your [sub] array begins (in this case, let's say the first pointer points to the location in memory where your first of four arrays is). Now this array needs to be malloc for 4 "spaces" (in this case, let's assume of type INT). (so array[0] = the first array) If you wanted to set the values 1, 2, 3, 4 within that array, you'd be specifying array[0][0], array[0][1], array[0][2], array[0][3]. This would then be repeated for the other 3 arrays that create this table.
Hope this helps!

define a two-dimensional global array which its size have to be scanned from a file

I want to define a two dimensional array as a global variable:
int visited[nbVertices][nbVertices];
but the problem that I have to scan the "nbVertices" from a file. is there anyway to fix this problem ?
I think it may be fixed by using pointers, but I don't know how to do it.
So, while we're at it: you don't need the array to be global. Hence, you can just use variable-length arrays and pass the array to all the functions that need it:
void printArray(int n, int k, int arr[n][k])
{
for (int i = 0; i < n; i++) {
for (int j = 0; j < k; j++) {
printf("%6d", arr[i][j]);
}
printf("\n");
}
}
int main()
{
// get user input in the format "n" <space> "k"
char *end;
char buf[LINE_MAX];
if (!fgets(buf, sizeof buf, stdin))
return -1;
// create array, fill it with random stuff
int n = strtol(buf, &end, 10);
int k = strtol(end, NULL, 10);
int a[n][k];
for (int i = 0; i < n; i++) {
for (int j = 0; j < k; j++) {
a[i][j] = random();
}
}
// print it
printArray(n, k, a);
return 0;
}
Use malloc.
Your code might look something like this:
// somewhere in file, global
int **visited;
// somewhere in your code, when you read nbVertices
visited = malloc(sizeof(int*) * nbVertices);
for(size_t i = 0; i < nbVertices; i++)
visited[i] = malloc(sizeof(int) * nbVertices);
there shouldn't be any major differences using visited

Creating 2D array in single malloc() call

#include <stdio.h>
#include <stdlib.h>
#define MAX_ROWS 5
#define MAX_COLS 5
int globalvariable = 100;
void CreateMatrix(int ***Matrix)
{
int **ptr;
char *cp;
int i = 0;
*Matrix = (int**)malloc((sizeof(int*) * MAX_ROWS) + ((MAX_ROWS * MAX_COLS)*sizeof(int)));
ptr = *Matrix;
cp = (char*)((char*)*Matrix + (sizeof(int*) * MAX_ROWS));
for(i =0; i < MAX_ROWS; i++)
{
cp = (char*)(cp + ((sizeof(int) * MAX_COLS) * i));
*ptr = (int*)cp;
ptr++;
}
}
void FillMatrix(int **Matrix)
{
int i = 0, j = 0;
for(i = 0; i < MAX_ROWS; i++)
{
for(j = 0; j < MAX_COLS; j++)
{
globalvariable++;
Matrix[i][j] = globalvariable;
}
}
}
void DisplayMatrix(int **Matrix)
{
int i = 0, j = 0;
for(i = 0; i < MAX_ROWS; i++)
{
printf("\n");
for(j = 0; j < MAX_COLS; j++)
{
printf("%d\t", Matrix[i][j]);
}
}
}
void FreeMatrix(int **Matrix)
{
free(Matrix);
}
int main()
{
int **Matrix1, **Matrix2;
CreateMatrix(&Matrix1);
FillMatrix(Matrix1);
DisplayMatrix(Matrix1);
FreeMatrix(Matrix1);
getchar();
return 0;
}
If the code is executed, I get the following error messages in a dialogbox.
Windows has triggered a breakpoint in sam.exe.
This may be due to a corruption of the heap, which indicates a bug in sam.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while sam.exe has focus.
The output window may have more diagnostic information.
I tried to debug in Visual Studio, when printf("\n"); statement of DisplayMatrix() is executed, same error message is reproduced.
If I press continue, it prints 101 to 125 as expected. In Release Mode, there is no issue !!!.
please share your ideas.
In C it is often simpler and more efficient to allocate a numerical matrix with calloc and use explicit index calculation ... so
int width = somewidth /* put some useful width computation */;
int height = someheight /* put some useful height computation */
int *mat = calloc(width*height, sizeof(int));
if (!mat) { perror ("calloc"); exit (EXIT_FAILURE); };
Then initialize and fill the matrix by computing the offset appropriately, e.g. something like
for (int i=0; i<width; i++)
for (int j=0; j<height; j++)
mat[i*height+j] = i+j;
if the matrix has (as you show) dimensions known at compile time, you could either stack allocate it with
{ int matrix [NUM_COLS][NUM_ROWS];
/* do something with matrix */
}
or heap allocate it. I find more readable to make it a struct like
struct matrix_st { int matfield [NUM_COLS][NUM_ROWS]; };
struct matrix_st *p = malloc(sizeof(struct matrix_st));
if (!p) { perror("malloc"); exit(EXIT_FAILURE); };
then fill it appropriately:
for (int i=0; i<NUM_COLS; i++)
for (int j=0; j<NUM_ROWS, j++)
p->matfield[i][j] = i+j;
Remember that malloc returns an uninitialized memory zone so you need to initialize all of it.
A two-dimensional array is not the same as a pointer-to-pointer. Maybe you meant
int (*mat)[MAX_COLS] = malloc(MAX_ROWS * sizeof(*mat));
instead?
Read this tutorial.
A very good & complete tutorial for pointers, you can go directly to Chapter 9, if you have in depth basic knowledge.

Resources