I've got a small part of simple code that keeps giving me segmentation fault each time I go through the realloc for loop in the second if statement.
*x = (int**)realloc(*x,nNew*sizeof(int*));
for(int i=0;i<n;i++)
x[i] = (int*) realloc(x[i],nNew*sizeof(int)); // seg fault
I think that the memory allocation has been done correctly (apparently not) but I cannot find the error.In the first if statement (where I de-allocate memory) it works correctly.
Sorry for the bad format.
void update(int **x,int n,int nNew)
{
int temp;
if(n>nNew)
{
*x = (int **) realloc(*x,nNew*sizeof(int*));
for(int i=0;i<n;i++)
*(x+i) =(int *) realloc(x[i],nNew*sizeof(int));
printf("temp %d",x[nNew-1][nNew-1]);
}
else if(n<nNew)
{
temp = x[n-1][n-1];
*x = (int**)realloc(*x,nNew*sizeof(int*));
for(int i=0;i<n;i++)
x[i] = (int*) realloc(x[i],nNew*sizeof(int)); // seg fault
printf("temp %d",**temp);
for(int i=n;i<(nNew);i++)
{
for(int j=n;j<(nNew);j++)
x[i][j] = temp;
}
}
}
int main()
{
int nNew = 9;
int n = 8;
int **x = (int **) malloc(n*sizeof(int*));
for (int i=0; i<n; i++)
x[i] = (int *)malloc(n * sizeof(int));
int count=0 ;
for(int i=0;i<n;i++)
{
count ++;
for(int j=0;j<n;j++)
x[i][j] = count;
}
update(x,n,nNew);
for(int i=0;i<nNew;i++)
free(x[i]);
free(x);
return 0;
}
You're not reallocating what you think you are.
When you do this:
*x = (int**)realloc(*x,nNew*sizeof(int*));
for(int i=0;i
Since x has type int **, *x has type int *. Also, *x is the same as x[0]. So you're not reallocating the array of pointers on the first line but the first array of int. You need to call realloc on the original pointer, and you need to pass the address of that pointer so that the change is visible in the calling program.
Then for the reallocation of the individual arrays, you need to call realloc on the original n to grow or shrink them, then either free the extra rows if growing or malloc the newly added rows. In the growing case you want to realloc the array of pointers fisrt, and in the shrinking case you want to do that last.
So after those changes your update function should look like this:
void update(int ***x, int n, int nNew)
{
if(n>nNew) {
// shrink each row to be kept
for(int i=0;i<nNew;i++)
(*x)[i] = realloc((*x)[i],nNew*sizeof(int));
// free the extra rows
for(int i=nNew;i<n;i++)
free((*x)[i]);
// shrink the list of rows
*x = realloc(*x,nNew*sizeof(int*));
} else if(n<nNew) {
// grow the list of rows
*x = realloc(*x,nNew*sizeof(int*));
// grow the existing rows
for(int i=0;i<n;i++)
(*x)[i] = realloc((*x)[i],nNew*sizeof(int));
// create the new rows
for(int i=n;i<nNew;i++)
(*x)[i] = malloc(nNew*sizeof(int));
}
}
And you call it like this:
update(&x,n,nNew);
Related
Basically i understand pointers. But when it comes to dynamic allocation for matrices which also involve pointers, i'm getting lost in the process. I wanna know how can i translate this segment of code in order to understand it.
(*a)[i] = (int*)malloc((*m) * sizeof(int));
The function for reading the matrix looks like this:
void reading(int *n, int *m, int ***a) {
int i, j;
printf("n=");
scanf("%d", &*n);
printf("m=");
scanf("%d", &*m);
(*a) = (int**)malloc((*n) * sizeof(int*));
for (i = 0; i < *n; i++)
(*a)[i] = (int*)malloc((*m) * sizeof(int));
for (i = 0; i < *n; i++) {
for (j = 0; j < *m; j++) {
printf("a[%d][%d]=", i, j);
scanf("%d", &(*a)[i][j]);
}
}
}
And also what is the meaning of ***a in the declaration. I was told at college that te first asterisk stands for dynamic allocation and the other two's from the fact that is a matrix involved. For vectors dynamic allocation is **v and so on... but i can't naturally explain it in my mind in order understand what is happening in it.
First let me answer your question about this specific line:
(*a)[i] = (int*)malloc((*m) * sizeof(int));
What this is doing is allocating an array of exactly *m integers and saving a pointer to it into the array *a of pointers to int, which was previously allocated as:
(*a) = (int**)malloc((*n) * sizeof(int*));
Now, if it still isn't clear what is going on, re-writing the code in a more meaningful way will help. To make things easier, you can use temporary variables to work, and assign the values to the pointers passed as arguments only at the end of the function. Using more meaningful names also helps a lot.
void read_matrix(int *rows, int *columns, int ***matrix) {
int i, j, r, c;
int **mat;
printf("n = ");
scanf("%d", &r);
printf("m = ");
scanf("%d", &c);
// Allocate space for a matrix (i.e. an array of r integer pointers).
mat = malloc(r * sizeof(int*));
// Allocate space for each row of the matrix (i.e. r arrays of c integers).
for (i = 0; i < r; i++)
mat[i] = malloc(c * sizeof(int));
for (i = 0; i < r; i++) {
for (j = 0; j < c; j++) {
printf("a[%d][%d] = ", i, j);
scanf("%d", &mat[i][j]);
}
}
*rows = r;
*columns = c;
*matrix = mat;
}
Since we now moved the assignment of the values to the arguments at the end of the function, we got rid of all the annoying pointer dereference operators (*), and the code looks way cleaner.
You can see that what previously was:
(*a)[i] = (int*)malloc((*m) * sizeof(int));
now became:
mat[i] = malloc(c * sizeof(int));
Which is much easier to understand. This is allocating space for an array (a row of the matrix) holding c integers.
What previously was:
(*a) = (int**)malloc((*n) * sizeof(int*));
now became:
mat = malloc(r * sizeof(int*));
This is allocating an array of r integer pointers (which means a matrix of r rows, if each pointer points to a row).
You don't show how this function is called, but presumably it looks something like this:
int n, m;
int **matrix;
reading(&n, &m, &matrix);
So in this context, matrix is defined as a pointer-to-pointer. It can hold the address of the first element of an array of int *, each of which can hold the address of the first element of an array of int.
When &matrix is then passed to this function, you have a pointer-to-pointer-to-pointer, which is what the argument a of reading is. In this context, a contains a pointer to a single int **, specifically matrix in the calling function. By dereferecing a in reading, you're actually accessing matrix in the calling function.
So now getting to this line:
(*a) = (int**)malloc((*n) * sizeof(int*));
This allocates space for an array of *n int * and assigns that to *a, (i.e. matrix in the calling funtion. So now you have an array of int *. Now for this:
for (i = 0; i < *n; i++)
(*a)[i] = (int*)malloc((*m) * sizeof(int));
This loops through the elements of the int * array and assigns to each one a pointer to a memory block big enough for *m int.
So you now effectively have a 2D array of int. Note however that this is not the same as an actual 2D array of int which would be declared as int arr[n][m].
First, you are doing too many different things in a single function, which is making it a bit messy. I suggest that you separate out the logic to get the matrix size from the logic to create the matrix:
void get_size(int *n, int *m) {
printf("n=");
scanf("%d", n);
printf("m=");
scanf("%d", m);
}
int **create_matrix(int n, int m) {
int **matrix = malloc(n * sizeof(int*));
for (int i = 0; i < n; i++)
matrix[i] = malloc(m * sizeof(int));
return matrix;
}
void fill_matrix(int **matrix, int n, int m) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
printf("a[%d][%d]=", i, j);
scanf("%d", [i][j]);
}
}
}
From here it is a lot easier to see what is going on, with fewer *s and &s.
Your matrix is implemented as an array of arrays, so
int **matrix = malloc(n * sizeof(int*));
allocates memory for the outer array, while
matrix[i] = malloc(m * sizeof(int));
allocates memory for each of the inner arrays.
int ***a declares a to be a pointer to a pointer to pointer to an int. The caller is required to have their own int ** and to pass its address to this function. For example, the caller might define int **x; and pass &x to this function for the parameter a. I will use x to refer to the caller’s int **.
(*a) = (int**)malloc((*n) * sizeof(int*)); sets the caller‘s pointer (x) to point to space for *n pointers to int. This is preparation for fabricating a matrix of *n rows—memory will be allocated for each row, and we will have a pointer to that memory, so we need n pointers.
Then these lines:
for (i = 0; i < *n; i++)
(*a)[i] = (int*)malloc((*m) * sizeof(int));
allocate memory for *n rows. The second line allocates memory for an array of m int and sets x[i] to point to the first element of that memory. Note that since a is an int ***, *a is an int **, and (*a)[i] is an int *. Thus, *a points to an array of int * elements.
Finally, these lines:
for (i = 0; i < *n; i++) {
for (j = 0; j < *m; j++) {
printf("a[%d][%d]=", i, j);
scanf("%d", &(*a)[i][j]);
}
}
set each element of the *n by *m array: For each element x[i][j] (referred to as (*a)[i][j], it passes the address of the element (&(*a)[i][j]) to scanf to be set from the input stream.
I am a novice C programmer trying to write a function that dynamically allocates space for a 2D array. I am getting a segmentation fault when running this code & i'm not sure why.
#include <stdio.h>
#include <stdlib.h>
int allocate_space_2D_array(int **arr, int r, int c) {
int i,j;
arr = malloc(sizeof(int *) * r);
for (i = 0; i < r; i++)
arr[i] = malloc(sizeof(int *) * c);
for (i = 0; i < r; i++) {
for (j = 0; j < c; j++) {
printf("%p", arr[r][c]);
}
printf("\n");
}
return arr;
}
I expected to be able to print out and see the contiguous memory locations of each spot in the array, but I am never reaching that point in my code, because when I run it, i get a segmentation fault. Would appreciate any help.
Seeing your program i see 3 errors one while you allocate memory for 2D-array,one while you're printing and another one is how you declare the function.
First malloc is ok,the second one is wrong cause you already allocated memory for r(size of row) pointers so it's just like if you have * arr[r],so to allocate memory correctly now you should allocate memory just for int and not for int*.
Second error while printing you put as index for row and column the values r and c,but r and c are the size of matrix , as we know the size of an array or 2D-array goes from 0 to size-1,in your case goes from 0 to r-1 and from 0 to c-1.
Third error you should declare the function not as int but as int** cause you want to return a matrix so the return type is not int but int**.
I change your code to make it work correctly,it should be work.
int** allocate_space_2D_array(int **arr, int r, int c) {
int i,j;
arr = malloc(sizeof(int *) * r);
for (i = 0; i < r; i++)
arr[i] = malloc(sizeof(int ) * c);
for (i = 0; i < r; i++) {
for (j = 0; j < c; j++) {
printf("%p", arr[i][j]);
}
printf("\n");
}
return arr;
}
I want to declare 2D-array in .h file without given numbers of COLS nor ROWS (cause they are read somewhere from inside the main() )
I mean I could tried another way of doing this like below
if one of ROWS and COLS is given at the firsthand.
int COLS = 20;
int (*array)[COLS];
array = malloc((*array) * ROWS);
thus I tried like below:
below is 2d.h
int* a;
int** b;
int size;
below is test2d.c, inside int main(){}
read_size() //size value read from some file
a = malloc(sizeof(int) * size);
b = malloc(sizeof(*a) * size);
for(int i=0; i<size; i++){
for(int j=0; j<size; j++){
b[i][j] = i+j;
printf("ok");
}
}
//print all
should be printing all 0112 but the result is segmentation fault.
To allocate a 2D array you need to allocate the 2D pointer b, which you have done. After that you need to allocate memory for b[i] in a for loop as below
// cols and rows are input by user or other parts of program.
int **b;
b = malloc(sizeof(int*) * rows);
for(int i=0; i<rows; i++){
b[i] = malloc(sizeof(int) * cols);
}
The explanation for this is that b is an array of pointers to int. In each element of b you allocate an array of int. This gives you a 2D array.
If you want a rectangular (not jagged array), it's most efficient to allocate all the cells as a single block, then the row pointers can all point into that block:
#include <stdlib.h>
int **make_array(size_t height, size_t width)
{
/* assume this multiplication won't overflow size_t */
int *cells = malloc((sizeof *cells) * height * width);
int **rows = malloc((sizeof *rows) * height);
if (!rows || !cells) {
free(cells);
free(rows);
return 0;
}
/* now populate the array of pointers to rows */
for (size_t row = 0; row < height; ++row) {
rows[row] = cells + width * row;
}
return rows;
}
This also makes deallocation much simpler, as we no longer need a loop:
void free_array(int **a)
{
if (!a) return;
free(a[0]);
free(a);
}
I'm trying to generate a matrix of some arbitrary dimensions. I can do it just fine by calling scanf in main and then assigning matrix elements on a row by row basis, but trying to do it in a single function, outside of main, (and only if scanf() is called outside of main) gives me a segfault error:
int **genmat(int nrow, int ncol){
int i,j;
int **mat = (int**) malloc(sizeof(int)*ncol*nrow);
char rowbuff[16];
for(i=0; i < nrow; i++){
INPUT: scanf("%[^\n]%*c",rowbuff);
if(strlen(rowbuff) != ncol){
printf("Error: Input must be string of length %d\n", ncol);
goto INPUT;
}
else{
for(j=0; j < ncol; j++){
if(rowbuff[j] == '1'){
mat[i][j] = 1;
}
else{
mat[i][j] = 0;
}
}
}
}
return(mat);
}
The following works just fine:
int *genrow(int ncol, char *rowbuff){
int i;
int *row = malloc(sizeof(int)*ncol);
for(i=0;i<ncol;i++){
row[i] = rowbuff[i]%2;
}
return(row);
}
with the following in my main function to call genrow() for each row of the matrix:
for(i=0; i < row; i++){
INPUT: scanf("%[^\n]%*c",rowbuff);
if(strlen(rowbuff) != col){
printf("Error: Input must be string of length %d\n", col);
goto INPUT;
}
else{
int *newrow = genrow(col, rowbuff);
for(j=0; j < col; j++){
matrix[i][j] = newrow[j];
}
free(newrow);
newrow = NULL;
}
}
Why is the behavior different in these two contexts?
Dynamically allocated 2D arrays are unfortunately burdensome and ugly in C. To properly allocate one, it is very important that you do so with a single call to malloc, just as you tried to do. Otherwise it won't be a 2D array, but instead some segmented, slow look-up table.
However, the result of that malloc call will be a pointer to a 2D array, not a pointer-to-pointer. In fact, pointer-pointers have nothing to do with 2D arrays whatsoever - this is a widespread but incorrect belief.
What you should have done is this:
int (*mat)[nrow][ncol] = malloc( sizeof(int[nrow][ncol] );
This is an array pointer to a 2D array. This syntax is already a bit burdensome, but to make things worse, it is not easy to pass this array pointer back to main, because it is a local pointer variable. So you would need to use a pointer to an array pointer... and there's no pretty way to do that. It goes like this:
void genmat (size_t nrow, size_t ncol, int (**mat)[nrow][ncol] )
{
*mat = malloc( sizeof(int[nrow][ncol]) );
To ease usage a bit, you can create a temporary pointer to rows, which doesn't require multiple levels of indirection and is therefore much easier to work with:
int (*matrix)[ncol] = *mat[0]; // in the pointed-at 2D array, point at first row
for(size_t r=0; r<nrow; r++) // whatever you want to do with this matrix:
{
for(size_t c=0; c<ncol; c++)
{
matrix[r][c] = 1; // much more convenient syntax than (**mat)[r][c]
}
}
From main, you'll have to call the code like this:
size_t row = 3;
size_t col = 4;
int (*mat)[row][col];
genmat(row, col, &mat);
Example:
#include <stdio.h>
#include <stdlib.h>
void genmat (size_t nrow, size_t ncol, int (**mat)[nrow][ncol] )
{
*mat = malloc( sizeof(int[nrow][ncol]) );
int (*matrix)[ncol] = *mat[0];
for(size_t r=0; r<nrow; r++)
{
for(size_t c=0; c<ncol; c++)
{
matrix[r][c] = 1;
}
}
}
void printmat (size_t nrow, size_t ncol, int mat[nrow][ncol])
{
for(size_t r=0; r<nrow; r++)
{
for(size_t c=0; c<ncol; c++)
{
printf("%d ", mat[r][c]);
}
printf("\n");
}
}
int main (void)
{
size_t row = 3;
size_t col = 4;
int (*mat)[row][col];
genmat(row, col, &mat);
printmat(row, col, *mat);
free(mat);
return 0;
}
Please note that real code needs to address the case where malloc returns NULL.
I assume the problems is withint **mat = (int**) malloc(sizeof(int)*ncol*nrow);
You are trying to allocate the a 2D array right? But this isn't the correct method to allocate the memory. You can't allocate the whole chunk of memory one short.
What you should be doing here is, allocate the memory for all the rows(basically pointer to store the column address) and then for columns
int **mat= (int **)malloc(nrow * sizeof(int *));
for (i=0; i<nrow; i++)
mat[i] = (int *)malloc(ncol * sizeof(int));
Refer this link for more info http://www.geeksforgeeks.org/dynamically-allocate-2d-array-c/
I need to allocate contiguous space for a 3D array. (EDIT:) I GUESS I SHOULD HAVE MADE THIS CLEAR IN THE FIRST PLACE but in the actual production code, I will not know the dimensions of the array until run time. I provided them as constants in my toy code below just to keep things simple. I know the potential problems of insisting on contiguous space, but I just have to have it. I have seen how to do this for a 2D array, but apparently I don't understand how to extend the pattern to 3D. When I call the function to free up the memory, free_3d_arr, I get an error:
lowest lvl
mid lvl
a.out(2248,0x7fff72d37000) malloc: *** error for object 0x7fab1a403310: pointer being freed was not allocated
Would appreciate it if anyone could tell me what the fix is. Code is here:
#include <stdio.h>
#include <stdlib.h>
int ***calloc_3d_arr(int sizes[3]){
int ***a;
int i,j;
a = calloc(sizes[0],sizeof(int**));
a[0] = calloc(sizes[0]*sizes[1],sizeof(int*));
a[0][0] = calloc(sizes[0]*sizes[1]*sizes[2],sizeof(int));
for (j=0; j<sizes[0]; j++) {
a[j] = (int**)(a[0][0]+sizes[1]*sizes[2]*j);
for (i=0; i<sizes[1]; i++) {
a[j][i] = (int*)(a[j]) + sizes[2]*i;
}
}
return a;
}
void free_3d_arr(int ***arr) {
printf("lowest lvl\n");
free(arr[0][0]);
printf("mid lvl\n");
free(arr[0]); // <--- This is a problem line, apparently.
printf("highest lvl\n");
free(arr);
}
int main() {
int ***a;
int sz[] = {5,4,3};
int i,j,k;
a = calloc_3d_arr(sz);
// do stuff with a
free_3d_arr(a);
}
Since you are using C, I would suggest that you use real multidimensional arrays:
int (*a)[sz[1]][sz[2]] = calloc(sz[0], sizeof(*a));
This allocates contiguous storage for your 3D array. Note that the sizes can be dynamic since C99. You access this array exactly as you would with your pointer arrays:
for(int i = 0; i < sz[0]; i++) {
for(int j = 0; j < sz[1]; j++) {
for(int k = 0; k < sz[2]; k++) {
a[i][j][k] = 42;
}
}
}
However, there are no pointer arrays under the hood, the indexing is done by the magic of pointer arithmetic and array-pointer-decay. And since a single calloc() was used to allocate the thing, a single free() suffices to get rid of it:
free(a); //that's it.
You can do something like this:
int ***allocateLinearMemory(int x, int y, int z)
{
int *p = (int*) malloc(x * y * z * sizeof(int));
int ***q = (int***) malloc(x * sizeof(int**));
for (int i = 0; i < x; i++)
{
q[i] = (int**) malloc(y * sizeof(int*));
for (int j = 0; j < y; j++)
{
int idx = x*j + x*y*i;
q[i][j] = &p[idx];
}
}
return q;
}
void deallocateLinearMemory(int x, int ***q)
{
free(q[0][0]);
for(int i = 0; i < x; i++)
{
free(q[i]);
}
free(q);
}
I use it and works fine.