The following is my code and I cannot figure out where I am going wrong to free my 2d array.
I know that the error happens at this line: free(arr[i]); and I also know that I have to do this loop to free each integer before freeing the entire array later. Can anyone spot the bug here? I get no compilation errors, but once running my executable, there is a huge backtrace output for the free function.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int h = 4;
int w = 2;
int i, j;
int **arr = (int**)malloc(sizeof(int*) * h);
arr[0] = (int*)malloc(sizeof(int) * w * h);
for (i=1; i<h; i++)
{
arr[i] = arr[0] + (w*i);
}
int count = 0;
for (i=0; i<h; i++)
{
for (j=0; j<w; j++)
{
arr[i][j] = count++;
}
}
for (i=0; i<h; i++)
{
for (j=0; j<w; j++)
{
printf("Array[%d][%d] = %d ", i, j, arr[i][j]);
}
printf("\n");
}
for (i=0; i<h; i++)
{
free(arr[i]);
}
free(arr);
/*printf("\nAfter freeing the array it becomes:\n");
for (i=0; i<h; i++)
{
for (j=0; j<w; j++)
{
printf("Array[%d][%d] = %d ", i, j, arr[i][j]);
}
printf("\n");
}*/
}
you are allocating memory for arr[0] = (int*)malloc(sizeof(int) * w * h); only but while freeing the allocated space you are freeing up to h count, for (i=0; i<h; i++){free(arr[i]);}. You should have allocated this way as well using the same loop.
The memory you are allocating in the call
arr[0] = (int*)malloc(sizeof(int) * w * h);
is enough for the entire 2D array. If you want to use this approach, i.e., allocate memory for the 2D array in a single call to malloc, you can do so by casting the returned pointer to pointer-to-array of w elements. Then you can also free the memory in a single call to free. No need to use the for-loop. See the code below.
int main()
{
int h = 4;
int w = 2;
int i, j;
int (*arr)[w] = (int(*)[w])malloc(sizeof(int)*h*w); // pointer to array of w ints
int count = 0;
for (i=0; i<h; i++) {
for (j=0; j<w; j++) {
arr[i][j] = count++;
}
}
for (i=0; i<h; i++) {
for (j=0; j<w; j++) {
printf("Array[%d][%d] = %d ", i, j, arr[i][j]);
}
printf("\n");
}
free(arr); //<-- free the 2D array in a single free
return 0;
}
When you use your malloc's you allocate only the first position of the array
arr[0] = (int*)malloc(sizeof(int) * w * h);
This means than when you have to free your memory you need to call free(arr[0]) and then free(arr)
This will not give you an error.
Anyway, I don't think this is what you want to do. You probably want a solution more on the lines of:
int **arr = (int**)malloc(sizeof(int*) * h);
for (int i = 1; i < h ; ++i){
arr[i] = (int*)malloc(sizeof(int) * w); // with the correct size you want
}
This will allocate h pointers in the array for use, then you can free the memory like you did in your example
EDIT: Please note that like #AndrewHenle correctly pointed out in his comment this solution doesn't allocate a true 2D array but just an array of pointers to arrays. For a way to properly allocate a 2D array please see this related question
//for (i=0; i<h; i++) { free(arr[i]); }//error
free(arr[0]); //true
free(arr);
Related
I learnt about the concept of array of pointers and ragged arrays, but i'm not able to understand why my code isn't working.
#include<stdio.h>
int main(void)
{
int* b[10] ;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
scanf_s("%d", (*(b+i)+j));
}
}
return 0;
}
There are multiple issues with your code, so I will just post the corrected one with explanations:
int *b[10];
for (int i = 0; i < 3; i++) {
// you need to allocate memory to each pointer inside your array as well
// I have allocated for 3, since you scan 3 integers
b[i] = malloc(3 * sizeof(int));
for (int j = 0; j < 3; j++) {
// use scanf like this, you need the address not the value of variable you are scanning
scanf("%d", (*(b + i) + j));
}
}
You need to include the header file for malloc.
#include <stdlib.h>
Also, don't forget to free the dynamically allocated memory later to avoid memory leaks.
You are declaring an array of pointers:
int* b[10];
you need to allocate memory for each of those pointers, namely:
for (int i = 0; i < 10; i++) {
b[i] = malloc(3 * sizeof(int));
}
From Difference between scanf and scanf_s one can read:
scanf originally just reads whatever console input you type and assign
it to a type of variable.
(..)
scanf_s has an argument(parameter) where you can specify the buffer size and actually control the limit of the input so you don't crash the whole building.
Therefore, what you need is scanf, hence change your code from:
scanf_s("%d", (*(b+i)+j));
to
scanf("%d", (*(b+i)+j));
You should also check the returning value of the scanf function, and free the memory of the dynamically allocated array.
An example of a full running code:
#include<stdio.h>
#include <stdlib.h>
int main(void)
{
int array_size = 3;
int* b[array_size] ;
// Allocate memory for my array
for (int i = 0; i < array_size; i++)
b[i] = malloc(3 * sizeof(int));
int scanf_value = 0;
for (int i = 0; i < array_size; i++)
for (int j = 0; j < 3; j++){
if(scanf("%d", &b[i][j]) != 1){
while(getchar()!='\n'); // clean the input buffer
printf("Invalid Input! Add just numbers\n");
j--;
}
}
// print those elements
for (int i = 0; i < array_size; i++)
for (int j = 0; j < 3; j++)
printf("%d ",b[i][j]);
// lets free the memory
for (int i = 0; i < array_size; i++)
free(b[i]);
return 0;
}
scanf_s takes an address of a variable but you are passing a value. Doesn't your compiler complain? If not, bump up the warning/errors levels. Others already told you that you need to allocate memory for the array pointers to point at. If this was production code remember to free().
I need to write a program that will allocate the memory for multiplication table. The problem is that single call of malloc, calloc and realloc is limited to 80 bytes and I don't know how to allocate memory stage by stage.
If anyone could help me I would be grateful.
Here is what I have tried already. It works if I allocate the memory for 400 bytes in one call.
int main()
{
int row = 10;
int col = 10;
int w=0;
int k=0;
int *tab = (int *)malloc(row*col*sizeof(int));
if(tab == NULL)
{
printf("Failed to allocate memory");
return 8;
}
int i=0;
for (w=0; w<row; w++)
{
for(k=0; k<col; k++)
{
*(tab+w*col+k) = ++i;
}
}
for (w=0; w<row; w++){
for(k=0; k<col; k++){
printf("%3d ", *(tab+w*col+k) );
}
printf("\n");
}
free(tab);
return 0;
}
Nested mallocs() are what you'll need to use. But, be careful, because you'll also need to use several frees()!
// 80 bytes
int** table = malloc(row * sizeof(int*));
for (int i = 0; i < row; i++) {
// 80 bytes
table[i] = malloc(col * sizeof(int));
}
// The 6th element in the first row is set to 5.
table[0][5] = 5;
I'm trying to create a function to initialise a Matrix structure with its n*n dimensions and an array of elements. However the values from the array passed to the function aren't being correctly assigned to the array in the matrix (see output).
What's causing the problem and is there a better way of doing this?
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int rows;
int cols;
double *data;
} Matrix;
Matrix loadMatrix(int rows, int cols, double *data); //initialise matrix with elements in 'data'
void printMatrix(Matrix m);
int main(void) {
double data[4] = {1,2,3,4};
Matrix m = loadMatrix(2, 2, data);
printMatrix(m);
free(m.data);
return 0;
}
Matrix loadMatrix(int rows, int cols, double * elements)
{
Matrix result;
result.rows = rows;
result.cols = cols;
result.data = (double *)calloc(rows * cols, sizeof(double));
for(int i = 0; i < rows * cols; i++) {
*result.data = *elements; //copy each element to Matrix instance
result.data++;
elements++;
}
return result;
}
void printMatrix(Matrix m)
{
printf("\nRows: %d\tColumns: %d\n", m.rows, m.cols);
for(int i = 0; i < m.rows; i++) {
for(int j = 0; j < m.cols; j++) {
printf("%.0lf ", *m.data);
m.data++;
}
printf("\n");
}
}
Output
Rows: 2 Columns: 2
0 0
0 0
double free or corruption (out)
exit status -1
In this loop:
for(int i = 0; i < rows * cols; i++) {
*result.data = *elements; //copy each element to Matrix instance
result.data++;
elements++;
}
You're changing what result.data points to on each iteration of the loop. When the loop ends, it points to the end of the allocated array.
When you subsequently print the array:
for(int i = 0; i < m.rows; i++) {
for(int j = 0; j < m.cols; j++) {
printf("%.0lf ", *m.data);
m.data++;
}
printf("\n");
}
You read past the end of the array and move m.data further past the end of the array. This invokes undefined behavior. You further invoke undefined behavior when you call free because m.data no longer points to the value returned by malloc.
You can fix this by using array indexing syntax in both places instead of modifying the pointer value.
In loadMatrix:
for(int i = 0; i < rows * cols; i++) {
result.data[i] = elements[i];
}
In printMatrix:
for(int i = 0; i < m.rows; i++) {
for(int j = 0; j < m.cols; j++) {
printf("%.0lf ", m.data[i*m.rows+j);
}
printf("\n");
}
You are breaking your result.data pointer by incrementing it in loadMatrix. It no longer points to start of the allocated memory when you try to print or free it.
Replace pointer arithmetric nonsense with array indexing to avoid messing the pointer and making the code more simple:
for(int i = 0; i < rows * cols; i++) {
result.data[i] = elements[i];
}
Note that you have the same problem in printMatrix function, but since you don't return the modified copy, it has no effect further in the code. Still I would recommend using array indexing there too.
I'm trying to multiply 2 dynamically allocated arrays. I'm having 2 problems:
When I try unequal sized arrays like [2],[3] and [3],[2] I got a segmentation fault 11, and after staring at my allocations I still can't figure out why.
My final array is formatted with the correct rows and columns, but it displays all 0's.
I'm assuming that this is because I didn't allocate the memory correctly.
-
#include <stdio.h>
#include <stdlib.h>
int main()
{
int **a, **b, **c; //pointers to arrays
int m1_r,m1_c,m2_r,m2_c; //declaring arrays
int i,j,k;
printf("\n");
again://repeat if first matrixes are bad
printf("Enter rows and columns for the first matrix.\n");//first matrix
scanf("%d%d" ,&m1_r,&m1_c);
printf("Enter rows and Columns for the second matrix.\n");//second matrix
scanf("%d%d",&m2_r,&m2_c);
if(m1_c!=m2_r) {
printf("You tried to break my code. Nice try.");
goto again;
}
//memory for first matrix
a = malloc(m1_r * sizeof(int *));
for(i=0; i < m1_r; i++) {
a[i] = malloc(m1_c * sizeof(int));
}
//memory for second matrix
b = malloc(m2_r * sizeof(int *));
for(i=0; i < m2_r; i++) {
b[i] = malloc(m2_c * sizeof(int));
}
//memory for 3rd matrix
c = malloc(m1_r * sizeof(int *));
for(i=0; i < m2_r; i++) {
c[i] = malloc(m2_c * sizeof(int));
}
//input 1st matrix
printf("Enter the numbers of the first matrix.\n");
for (i=0; i<m1_r; i++) {
for (j = 0; j<m1_c; j++) {
scanf("%d", &a[i][j]);
}
}
//input 2nd matrix
printf("Enter the second of the first matrix.\n");
for (i=0; i<m1_r; i++) {
for (j = 0; j<m1_c; j++) {
scanf("%d", &b[i][j]);
}
}
printf("\n");
printf("1st matrix looks like this:\n");
//print 1st matrix
for (i=0; i<m1_r; i++) {
for (j = 0; j<m1_c; j++) {
printf("%d\t", a[i][j]);
}
printf("\n");
}
//print 2nd matrix
printf("\n");
printf("2nd matrix looks like this:\n");
//print 2st matrix
for (i=0; i<m2_r; i++) {
for (j = 0; j<m2_c; j++) {
printf("%d\t", b[i][j]);
}
printf("\n");
}
//initialize result matrix to 0
for(i=0; i<m2_r; i++)
for(j=0; j<m2_c; j++) {
c[i][j]=0;
}
//multipication
for(i=0; i<m1_r; i++)
for(j=0; j<m2_c; j++)
for(k=0; k<m1_c; k++) {
c[i][j]+= a[i][k]*b[k][j];
}
//print result
printf("\nThe result of the matrix multiplication is:");
for(i=0; i<m1_r; i++) {
printf("\n");
for(k=0; k<m2_c; k++) {
printf("%d\t", c[i][j]);
}
}
printf("\n");
return 0;
}
You allocate the wrong amount of memory for the third matrix:
c = malloc(m1_r * sizeof(int *));
for(i=0; i < m2_r; i++)
The loop count should be the same as the number of pointers you malloc.
To avoid this sort of error, consider making a function which you pass in the dimensions and it returns the pointer.
Later on, you overwrite its bounds using different indices again:
for(i=0;i<m2_r;i++)
for(j=0;j<m2_c;j++)
{
c[i][j]=0;
}
Then you overwrite the bounds of b (it was m2_r and m2_c):
for (i=0; i<m1_r; i++) {
for (j = 0; j<m1_c; j++) {
scanf("%d", &b[i][j]);
}
}
To avoid this sort of error, you could use a better naming convention for your variables; and also consider using a struct which holds each pointer plus its dimension variables. Then you can have a function that zeroes any matrix and you only need to pass it a pointer to one of your matrix structs.
BTW if you use calloc instead of malloc then you don't need this loop at all (although you might want to have this function anyway so that you can zero a matrix).
Also you should check for success of scanf and malloc.
There are hell lot of bugs in your code:
First
//memory for 3rd matrix
c = malloc(m1_r * sizeof(int *));
for(i=0; i < m2_r; i++) <----- error: used m2_r instead of m1_r
You assigned m1_r and loop till m2_r.
Second
//input 2nd matrix
printf("Enter the second of the first matrix.\n");
for (i=0; i<m1_r; i++) { <----- error: used m1_r instead of m2_r
for (j = 0; j<m1_c; j++) { <----- error: used m1_c instead of m2_c
scanf("%d", &b[i][j]);
}
}
You are using rows and columns of 1st matrix.
Third
//initialize result matrix to 0
for(i=0; i<m2_r; i++) <----- error: used m2_r instead of m1_r
for(j=0; j<m2_c; j++) {
c[i][j]=0;
}
You used row value of second matrix rather than the first matrix
gcc 4.6.2 c89
Allocating memory for a 2D array and filling with characters.
However, I don't seem to be filling as when I print nothing is displayed.
Am I doing something wrong here?
char **attributes = NULL;
/* TODO: Check for memory being allocated */
attributes = malloc(3 * sizeof(char*));
int i = 0;
int k = 0;
for(i = 0; i < 3; i++) {
for(k = 0; k < 5; k++) {
sdp_attributes[i] = malloc(5 * sizeof(char));
sdp_attributes[i][k] = k;
}
}
for(i = 0; i < 3; i++) {
for(k = 0; k < 5; k++) {
printf("attributes[i][k] [ %c ]\n", attributes[i][k]);
}
}
Many thanks for any advice,
Two major issues:
First Issue:
for(i = 0; i < 3; i++) {
for(k = 0; k < 5; k++) {
sdp_attributes[i] = malloc(5 * sizeof(char));
You are reallocating sdp_attributes[i] at each iteration of the inner loop - thereby overwriting it each time. You probably wanted this instead:
for(i = 0; i < 3; i++) {
sdp_attributes[i] = malloc(5 * sizeof(char));
for(k = 0; k < 5; k++) {
Second Issue:
sdp_attributes[i][k] = k;
You are basically writing the lower ascii characters. Most of them are not printable.
Something like this might do what you want:
sdp_attributes[i][k] = k + '0';
You probably want:
for (i = 0; i < 3; i++)
{
attributes[i] = malloc(5 * sizeof(char));
for (k = 0; k < 5; k++)
{
attributes[i][k] = k;
}
}
This ignores error checking on the allocation.
It also fixes the name of the array to match the declaration, but your code either wasn't compiling (don't post non-compiling code unless your question is about why it doesn't compile!) or you have another variable called sdp_attributes declared somewhere which you weren't showing us.
Your code was leaking a lot of memory. Each time around the k-loop, you allocated a new array of 5 characters and stored the pointer in attributes[i] (or sdp_attributes[i]), storing the new pointer over what was there before, so you overwrote the value of the first 4 pointers. You could not possibly free the first four items - they were lost irretrievably. Also, on the last iteration, you initialized the 5th element of the final array, but the previous 4 were not initialized and therefore contained indeterminate garbage.
Also, in your printing loop, the values in the array are control characters ^#, ^A, ^B, ^C and ^D; these do not necessarily print well with %c (especially not ^#, which is also known as NUL or '\0'). The printf() statement might be better written as:
printf("attributes[%d][%d] [ %d ]\n", i, k, attributes[i][k]);
This prints the array indexes (rather than simply the characters [i][k] for each entry), and prints the control characters as integers (since the char values are promoted to int when passed to printf()) rather than as control characters.
(It's also more conventional to use i and j for a pair of nested loops, and i, j, and k for triply nested loops, etc. However, that's a very minor issue.)
for(i = 0; i < 3; i++) {
for(k = 0; k < 5; k++) {
sdp_attributes[i] = malloc(5 * sizeof(char));
sdp_attributes[i][k] = k;
}
}
Your erasing the allocated memory every time you loop in the inner most loop.
Here is a correct version.
for(i = 0; i < 3; i++) {
sdp_attributes[i] = malloc(5 * sizeof(char));
for(k = 0; k < 5; k++) {
sdp_attributes[i][k] = k;
}
}
And you should fix your declaration:
attributes = malloc(3 * sizeof(char*));
to
sdp_attributes = malloc(3 * sizeof(char*));
Don't forget to free up all the memory allocated
for(i = 0; i < 3; i++)
{
free(sdp_attributes[i]);
}
free(sdp_attributes);
The correct way to allocate and assign elements to 2d array is as follows (but this is a int array, you can try and change it for char array):
One thing to note: As mentioned by #Mysticial, you should add/subtract '0' to your int value to get the char value when using ASCII character set (remember our itoa() functions!).
#include <stdio.h>
#include <stdlib.h>
int main()
{
int row, column;
int **matrix;
int i, j, val;
printf("Enter rows: ");
scanf("%d", &row);
printf("Enter columns: ");
scanf("%d", &column);
matrix = (int **) malloc (sizeof(int *) * row);
for (i=0 ; i<row ; i++)
matrix[i] = (int *) malloc (sizeof(int) * column);
val=1;
for (i=0 ; i<row ; i++) {
for (j=0 ; j<column; j++) {
matrix[i][j] = val++;
}
}
for (i=0 ; i<row ; i++) {
for (j=0 ; j<column; j++) {
printf("%3d ", matrix[i][j]);
}
printf("\n");
}
for (i=0 ; i<row ; i++)
free(matrix[i]);
free(matrix);
return 0;
}
Few points to note:
error handling should be added for malloc()
malloc()'ed memory must be free()'ed