No access to dynamically allocated array of 2 dimensions [duplicate] - c

This question already has an answer here:
Dynamic memory access only works inside function
(1 answer)
Closed 3 years ago.
I'm experimenting with the dynamic memory allocation of variable sized arrays. The function "ft_ultimate_range" seems to work, however, a problem arises when I try to access and print the values of each array's array. It signals either segmentation fault: 11, when compiled with GCC, or "subscripted value is neither array nor pointer nor vector" with [http://pythontutor.com/c][1]. I understand that this has to do with the use- or abuse of pointers... ehm
// allocate a grid of [n][n] with numbers ranging max-min
int *ft_ultimate_range(int **range, int min, int max)
{
int len, *ptr;
int count = min;
len = max - min;
ptr = range;
// allocate memory **arr
range = malloc(len * sizeof * range);
for(int i = 0; i < len; i++) {
range[i] = malloc(len * sizeof * ptr);
}
// assign values to allocated memory location
for(int i = 0; i < len; i++) {
for(int j = 0; j < len; j++) {
range[i][j] = count++;
}
count = min;
}
// free memory **range
for(int i = 0; i < len; i++) {
free(range[i]);
}
free(range);
return ptr;
}
int main()
{
int n;
n = 6 - 3;
int **ptr, *arr;
arr = ft_ultimate_range(ptr, 3, 6);
// print
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
printf("%d", ptr[i][j]);
}
}
return 0;
}
...a little pointer in the right direction would be very much appreciated.

Well, it obvious you are quite lost regarding how to return an allocated grid (pointer-to-pointer-to-int) from ft_ultimate_range() to main().
To begin, you do not need to pass range as a parameter to ft_ultimate_range(). Instead, make the return type int ** and declare int **range within ft_ultimate_range() and then allocate len pointers, and then allocate len integers per-pointer, assign the values and then return range and assign it to arr in main(), e.g.
#include <stdio.h>
#include <stdlib.h>
/* allocate a grid of [n][n] with numbers ranging max-min */
int **ft_ultimate_range (int min, int max)
{
int len = max - min,
**range = NULL,
count = min;
/* allocate len pointers */
range = malloc (len * sizeof * range);
if (!range) { /* validate EVERY allocation */
perror ("malloc-range");
return NULL;
}
/* allocate len int per-pointer */
for (int i = 0; i < len; i++) {
range[i] = malloc (len * sizeof *range[i]);
if (!range[i]) { /* validate alloation */
perror ("malloc-range[i]");
while (i--) /* free previously allocated rows */
free (range[i]); /* free pointers */
free (range);
return NULL;
}
}
/* assign values to allocated memory location */
for(int i = 0; i < len; i++) {
for(int j = 0; j < len; j++) {
range[i][j] = count++;
}
count = min;
}
return range;
}
(note: you MUST VALIDATE EVERY ALLOCATION...)
In main(), you don't need ptr, all you need is the int** pointer you will assign the return from ft_ultimate_range() to, e.g.
int main (void) {
int n = 6 - 3;
int **arr;
arr = ft_ultimate_range (3, 6);
if (!arr) /* validate return */
return 1;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
printf (" %d", arr[i][j]);
}
putchar ('\n');
free (arr[i]);
}
free (arr);
return 0;
}
(note: similarly, you must validate the return of ft_ultimate_range() before blindly looping through the values (that will not be there if an allocation failed)).
Example Use/Output
$ ./bin/alloc_a_grid
3 4 5
3 4 5
3 4 5
Memory Use/Error Check
In any code you write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.
It is imperative that you use a memory error checking program to insure you do not attempt to access memory or write beyond/outside the bounds of your allocated block, attempt to read or base a conditional jump on an uninitialized value, and finally, to confirm that you free all the memory you have allocated.
For Linux valgrind is the normal choice. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.
$ valgrind ./bin/alloc_a_grid
==29026== Memcheck, a memory error detector
==29026== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==29026== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==29026== Command: ./bin/alloc_a_grid
==29026==
3 4 5
3 4 5
3 4 5
==29026==
==29026== HEAP SUMMARY:
==29026== in use at exit: 0 bytes in 0 blocks
==29026== total heap usage: 4 allocs, 4 frees, 60 bytes allocated
==29026==
==29026== All heap blocks were freed -- no leaks are possible
==29026==
==29026== For counts of detected and suppressed errors, rerun with: -v
==29026== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Always confirm that you have freed all memory you have allocated and that there are no memory errors.
Look things over and let me know if you have further questions.

Here:
int **ptr, *arr;
arr = ft_ultimate_range(ptr, 3, 6);
ptr is NULL / uninitialised now. You cant allocate of this. malloc must be before call a function ft_ultimate_range. Here: printf("%d", ptr[i][j]); is NULL[i][j].
And you free **ptr in function ft_ultimate_range.
Hope this help.

int **ptr, *arr;
ptr is uninitialised at this point. It's value is indeterminate.
arr = ft_ultimate_range(ptr, 3, 6);
Passing an uninitialised value to a function is always wrong. If you hope the function will initialise it, you are mistaken. Read on pass by value.
ptr = range;
This assignment is wrong. You should have received a compiler warning about it. If you did not, upgrade your compiler ASAP. Never ignore warnings. Toying with a program that compiles with warnings is a waste of time.
for(int i = 0; i < len; i++) {
free(range[i]);
}
free(range);
At this point, every pointer in the program is invalid. Dereferencing them is undefined behaviour.
It isn't at all clear what your program is supposed to return. You are not using the return value anyway.
I suggest changing the signature of your function to this:
int** ft_ultimate_range(int min, int max)
Try to fit whatever you are trying to do in this mold.

Related

Segmentation fault when using sprintf in dynamically allocated array

I am converting integers to strings and adding them to a dynamically allocated array. The problem is that it is causing a segfault. I don't understand why it is happening.
#include <stdio.h>
#include <stdlib.h>
int main() {
char *x = malloc(10 * sizeof(char));
x[0] = malloc(10 * sizeof(char));
sprintf(x[0],"%d",10);
for(int i = 0; i < 10;i++){
free(x[i]);
}
free(x);
return 0;
}
To allocate an array whose elements are char*, the pointer to point the array should be char**, not char*.
Also you mustn't use values in buffer allocated via malloc() and not initiaized. The values are indeterminate and using them invokes undefined behavior.
#include <stdio.h>
#include <stdlib.h>
int main() {
/* correct type here (both variable and allocation size) */
char **x = malloc(10 * sizeof(char*));
x[0] = malloc(10 * sizeof(char));
sprintf(x[0],"%d",10);
/* initialize the other elements to pass to free() */
for (int i = 1; i < 10; i++) x[i] = NULL;
for(int i = 0; i < 10;i++){
free(x[i]);
}
free(x);
return 0;
}
If you want a dynamic allocated array of strings, you should declare your variable x as a pointer to an array of e.g. 32 chars. The you can allocate/deallocate an array of these using a single malloc and likewise a single free.
Like:
#define NUM_STRINGS 10
#define STRING_SIZE 32
int main() {
// declare x as a pointer to an array of STRING_SIZE chars
char (*x)[STRING_SIZE];
// Allocate space for NUM_STRINGS of the above array, i.e.
// allocate an array with NUM_STRINGS arrays of STRING_SIZE chars
x = malloc(NUM_STRINGS * sizeof *x);
if (x)
{
for (int i = 0; i < NUM_STRINGS; ++i)
{
sprintf(x[i], "%d", 10 + i);
}
for (int i = 0; i < NUM_STRINGS; ++i)
{
puts(x[i]);
}
free(x);
}
return 0;
}
Output:
10
11
12
13
14
15
16
17
18
19
The best way to determine the amount of memory to be used with malloc is this:
#include <stdio.h>
#include <stdlib.h>
#define N_STRINGS 10
#define STRING_SZ 10
int main() {
// if you use *x (the deferred subexpression) the compiler can calculate its
// sizeof easily, and no need to use a constant or something that has to be
// revised if you change the type of x. Also, calloc will give instead N_STRINGS
// pointers already initialized to NULL.
char **x = calloc(N_STRINGS, sizeof *x);
// to be able to free(x[i]) for all i, you need to initialize all pointers,
// and not only the first one.
int i; // I prefer this, instead of for(int i..., which is more portable with legacy code.
for (i = 0; i < N_STRINGS; i++) {
// char is warranted to be sizeof 1, you don't need to specify but the
// number of chars you want for each character array.
x[i] = malloc(STRING_SZ); // remember only STRING_SZ chars you have, so...
// better to use snprintf(), instead.
snprintf(x[i], // the buffer pointer
STRING_SZ, // the buffer size (STRING_SZ chars, incl. the final null char)
"%d", // the format string
10); // initialize all strings to the string "10" ???
}
// upto here we have made N_STRINGS + 1 calls to malloc...
// you should do something here to check that the allocations went fine, like
// printing the values or do some work on the strings, but that's up to you.
// now, everything should be fine for free() to work.
for(int i = 0; i < N_STRINGS; i++){
free(x[i]);
}
free(x); // ... and this is the N_STRINGS + 1 call to free.
return 0;
}
Check always that the number of free calls executed by your program has to be the same of the malloc calls you have made (before). A free call must free the memory allocated by one (and only one) call to malloc. You cannot free something that has not been acquired by malloc() (or calloc()) directly or indirectly. The same as it is bad use (but not necessary an error) to do a malloc that is not freed before the program ends (this is not true in non-hosted environments, e.g. embedded programs, in which the operating system doesn't deallocate the memory used by a program when it finishes, although)
By the way, the reason of your segmentation fault is precisely that you have made only two calls to malloc(), but you made 11 calls to free(). free() tries to free memory that malloc() has not allocated, or even worse, you don't own. Anyway, this drives you to Undefined Behaviour, which is something you don't desire in a program. In this case, you got a program crash.

How to free my double pointer allocated with malloc in another function

I want to free the double pointer, the problem is I was receiving as parameter another double pointer which actually makes a copy of the one I wanna free but that means it doesn't actually free the original, so how can I free the original in another function.
I've tried passing a double pointer as argument and a pointer pointing to this double pointer too but none of this worked.
int main(){
int ** matrix;
int rows = 5;
int cols = 6;
matrix = createMatrix(rows, cols);
printf("%d\n", matrix[2][3]);
freeMatrix(matrix, rows);
printf("%d\n", matrix[2][3]);
}
int** createMatrix(int row, int col){
int **m = (int **)malloc(row * sizeof(int*));
for(int x = 0; x < row; x++){
m[x] = (int *)malloc(col * sizeof(int));
}
return m;
}
void freeMatriz(int **m, int row){
for(int x = 0; x < row; x++){
free(m[x]);
}
free(m);
}
I was trying to print a position, lets say matrix[2][3] before and after the free; but both times its printing the number when after the print it shouldn't because that space in memory its supposed to be freed which apparently is not happening.
other than the typo in the
void freeMatriz(int **m, int row)
^
This is correctly freeing up the memory. The printf after freeing the matrix should actually result in an access violation. Which when testing with a MUCH larger 1024x2048 matrix this is what happens. My theories are as follows...
The memory has not yet been reclaimed and was still within program reach...
Some sort of delay in garbage collection or something.. lol
I'll leave it up to someone who might know why the second printf worked with such a small memory space being allocated to do so.. ;) would love to know the exact reason..
if you step through this with a debugger you will see the memory does get freed properly and if stepped through with a debugger the second printf results in an access violation... so it's gotta have something to do with the kernel.. :)
If you look at the Working Set and the Memory allocation in task manager, and put a system("pause") or getchar() (whatever type of break you want) before the free.. you can allocate a large matrix, check in in task manager... resume the program (with another break after the free). and you will see that the memory is being released. :)
Your two primary problems are:
You fail to validate the return of each allocation so malloc could have failed and you would have no way of knowing; and
After allocating storage for your integer values, you fail to initialize the memory, leaving the memory holding whatever garbage values happened to be present at that memory location (you can, and in the case of your integer allocations, use calloc to allocate and initialize at the same time, or use memset to do the same)
Your attempt to access matrix[2][3] before free() was simply accessing a uninitialized 4-bytes of memory containing whatever bits happened to be there. Your attempt to access matrix[2][3] after free() invokes Undefined Behavior. After free(), you can no longer validly access the memory that has been freed.
If you allocate, you must validate... It's not a matter of if malloc can fail returning NULL, it is a matter of when malloc fails returning NULL. To handle the failure case, you must always check the return of the allocation function (just as you do with every input function) you use. It is simple, if malloc returns NULL the allocation failed. So just check, e.g.
int **creatematrix (int row, int col)
{
int **m = malloc (row * sizeof *m);
if (!m) { /* if you allocate -- you must VALIDATE */
perror ("malloc-m");
return NULL;
}
for (int x = 0; x < row; x++) {
if (!(m[x] = malloc (col * sizeof *m[x]))) { /* ditto */
perror ("malloc-m[x]");
while (x--) /* on error free any allocated memory */
free (m[x]);
free (m); /* before returing NULL */
return NULL;
}
}
return m;
}
(note: before returning NULL you should free() any memory you have allocated up to that point to prevent a memory leak when you return NULL)
In your calling function (main() here), you need to validate the return of your creatematrix function to determine success/failure of the allocate -- before you make use of the memory, e.g.
int main (void) {
int **matrix,
rows = 5,
cols = 6;
if (!(matrix = creatematrix (rows, cols))) /* VALIDATE allocations */
exit (EXIT_FAILURE);
for (int i = 0; i < rows; i++) { /* loop initializing all values */
for (int j = 0; j < cols; j++) {
matrix[i][j] = i * cols + j;
printf (" %3d", matrix[i][j]); /* output all values */
}
putchar ('\n');
}
freematrix (matrix, rows); /* free all allocated memory */
}
Now you can free() all memory (which except for the typo of 'z' instead of 'x' you were doing correctly). Putting it altogether you could do:
#include <stdio.h>
#include <stdlib.h>
int **creatematrix (int row, int col)
{
int **m = malloc (row * sizeof *m);
if (!m) { /* if you allocate -- you must VALIDATE */
perror ("malloc-m");
return NULL;
}
for (int x = 0; x < row; x++) {
if (!(m[x] = malloc (col * sizeof *m[x]))) { /* ditto */
perror ("malloc-m[x]");
while (x--) /* on error free any allocated memory */
free (m[x]);
free (m); /* before returing NULL */
return NULL;
}
}
return m;
}
void freematrix (int **m, int row)
{
for (int x = 0; x < row; x++)
free (m[x]);
free (m);
}
int main (void) {
int **matrix,
rows = 5,
cols = 6;
if (!(matrix = creatematrix (rows, cols))) /* VALIDATE allocations */
exit (EXIT_FAILURE);
for (int i = 0; i < rows; i++) { /* loop initializing all values */
for (int j = 0; j < cols; j++) {
matrix[i][j] = i * cols + j;
printf (" %3d", matrix[i][j]); /* output all values */
}
putchar ('\n');
}
freematrix (matrix, rows); /* free all allocated memory */
}
Example Use/Output
$ ./bin/freematrix
0 1 2 3 4 5
6 7 8 9 10 11
12 13 14 15 16 17
18 19 20 21 22 23
24 25 26 27 28 29
Memory Use/Error Check
In any code you write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.
It is imperative that you use a memory error checking program to insure you do not attempt to access memory or write beyond/outside the bounds of your allocated block, attempt to read or base a conditional jump on an uninitialized value, and finally, to confirm that you free all the memory you have allocated.
For Linux valgrind is the normal choice. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.
$ valgrind ./bin/freematrix
==17080== Memcheck, a memory error detector
==17080== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==17080== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==17080== Command: ./bin/freematrix
==17080==
0 1 2 3 4 5
6 7 8 9 10 11
12 13 14 15 16 17
18 19 20 21 22 23
24 25 26 27 28 29
==17080==
==17080== HEAP SUMMARY:
==17080== in use at exit: 0 bytes in 0 blocks
==17080== total heap usage: 6 allocs, 6 frees, 160 bytes allocated
==17080==
==17080== All heap blocks were freed -- no leaks are possible
==17080==
==17080== For counts of detected and suppressed errors, rerun with: -v
==17080== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Always confirm that you have freed all memory you have allocated and that there are no memory errors.
Look things over and let me know if you have further questions.

How to print 2d matrices c

I am trying to simulate matrices using 2d arrays. But I am stuck at a run-time error. I am sure it occurs at printing function,but I couldn't find a solution at all.
obtn_matrix is a function that I use to create a matrix array. I didn't share the filler function which is used to get int values for the elements of the matrix array,so printed values will be whats in the memory. However, the problem is, I can't print the values at all. Program crashes after obtn_matrix.
int main()
{
int**matrix,m,n;
obtn_matrix(matrix,m,n);
prnt_matrix(matrix,m,n);
getch();
}
void prnt_matrix(int** matrix,int m,int n)
{
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
printf("%d ",matrix[i][j]);
}
printf("\n");
}
}
void obtn_matrix(int** matrix,int m,int n)
{
printf("Please enter the column number: ");
fflush(stdin);
scanf("%d",&m);
printf("Please enter the row number: ");
fflush(stdin);
scanf("%d",&n);
matrix=create_matrix(m,n);
}
The expected result is something like below:
4542 64 274 4234
765 53 3523 5345
5145 154 545 545
5435 543 545 14
I will handle the formatting (%4d etc). Kindly thanks in advance.
in obtn_matrix the assignment of matrix, m and n are not visible from main , you need to use pointer to them.
For instance, using array of int * because the dimensions are unknown at compile time:
#include <stdio.h>
#include <stdlib.h>
void prnt_matrix(int ** matrix,int m,int n)
{
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
printf("%d ",matrix[i][j]);
}
printf("\n");
}
}
int ** create_matrix(int m, int n)
{
int ** ma = calloc(m, sizeof(int*));
if (ma != NULL) {
int i, j;
for (i = 0; i != m; ++i) {
if ((ma[i] = malloc(n*sizeof(int))) == NULL)
return NULL;
for (j = 0; j != n; ++j) {
ma[i][j] = i*n + j;
}
}
}
return ma;
}
void obtn_matrix(int *** matrix,int * m,int * n)
{
printf("Please enter the row number: ");
fflush(stdin);
scanf("%d",m);
printf("Please enter the column number: ");
fflush(stdin);
scanf("%d",n);
*matrix=create_matrix(*m,*n);
}
void free_matrix(int ** matrix,int m,int n)
{
for(int i=0;i<m;i++)
{
if (matrix[i] == NULL)
/* matrix creation was aborted */
break;
free(matrix[i]);
}
free(matrix);
}
int main()
{
int ** matrix,m,n;
obtn_matrix(&matrix,&m,&n);
if (matrix != NULL) {
prnt_matrix(matrix,m,n);
free_matrix(matrix,m,n);
}
}
Compilation and execution :
pi#raspberrypi:~ $ gcc -pedantic -Wextra m.c
pi#raspberrypi:~ $ ./a.out
Please enter the row number: 3
Please enter the column number: 2
0 1
2 3
4 5
Execution under valgrind
pi#raspberrypi:~ $ valgrind ./a.out
==10436== Memcheck, a memory error detector
==10436== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==10436== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==10436== Command: ./a.out
==10436==
Please enter the row number: 3
Please enter the column number: 2
0 1
2 3
4 5
==10436==
==10436== HEAP SUMMARY:
==10436== in use at exit: 0 bytes in 0 blocks
==10436== total heap usage: 6 allocs, 6 frees, 2,084 bytes allocated
==10436==
==10436== All heap blocks were freed -- no leaks are possible
==10436==
==10436== For counts of detected and suppressed errors, rerun with: -v
==10436== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)
Note it is also possible to just alloc one array of m*n int but in that case rather than to use m[i][j]you need to do m[i*n+j]
If you haven't fully wrapped your head around the basic problem you are having, the problem is this, C passes parameters to functions by value. What this means is that when a parameter is passed, the function receives a copy of the variable which it is free to change -- but any changes are lost when the function returns.
One caveat to this is when an allocated pointer is passed. While it is still passed by value and the pointer will have its very own and very different address from the original, the memory address it holds as its value will still point to the same address as it does in the caller. This is no different that assigning int a = 5; and then passing a as a parameter, the function receives a copy of the variable, but it still contains 5.
However, if you attempt to allocate or reallocate such that the address of the pointer is changed, then any changes made in the function will be lost on return and not visible in the caller.
How Do You Handle This?
You have two options (1) pass the address of the pointer, so any changes to the address can be assigned to the dereferenced pointer (i.e. the original pointer address), or (2) change the return type from void to the type of pointer that needs to be returned and return the newly allocated/reallocated pointer for assignment in the caller.
For example, in your case, you need not pass matrix as a parameter to obtn_matrix() at all. You can simply use option (2) above and change the return type of obtn_matrix() to int ** and return create_matrix (*m, *n); at the end, e.g.
int **create_matrix (int m, int n)
{
int **matrix = malloc (m * sizeof *matrix);
if (matrix == NULL) {
perror ("malloc-matrix");
return NULL;
}
for (int i = 0; i < m; i++)
/* use calloc to initialize values zero */
if ((matrix[i] = calloc (n, sizeof **matrix)) == NULL) {
perror ("malloc-matrix[n]");
return NULL;
}
return matrix;
}
/* use pointers as parameters so the updated values of m, n are
* available back in the caller after the function returns. return
* int** for assignment back in the caller. Avoids becoming a
* 3-Star Programmer (not a compliment). return NULL on failure.
*/
int **obtn_matrix (int *m, int *n)
{
fputs ("enter number of rows: ", stdout);
if (scanf ("%d", m) != 1) { /* validate ALL user-input */
fputs ("error: invalid number of rows.\n", stderr);
return NULL;
}
fputs ("enter number of cols: ", stdout);
if (scanf ("%d", n) != 1) {
fputs ("error: invalid number of cols.\n", stderr);
return NULL;
}
return create_matrix (*m, *n);
}
Now putting it altogether, and making note that #bruno explains why you must pass the address of m, n (e.g. &m, &n) to obtn_matrix (option (1) above) so the updated values of m & n are available back in main() (the caller here), you could do something like:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int **create_matrix (int m, int n)
{
int **matrix = malloc (m * sizeof *matrix);
if (matrix == NULL) {
perror ("malloc-matrix");
return NULL;
}
for (int i = 0; i < m; i++)
/* use calloc to initialize values zero */
if ((matrix[i] = calloc (n, sizeof **matrix)) == NULL) {
perror ("malloc-matrix[n]");
return NULL;
}
return matrix;
}
/* use pointers as parameters so the updated values of m, n are
* available back in the caller after the function returns. return
* int** for assignment back in the caller. Avoids becoming a
* 3-Star Programmer (not a compliment). return NULL on failure.
*/
int **obtn_matrix (int *m, int *n)
{
fputs ("enter number of rows: ", stdout);
if (scanf ("%d", m) != 1) { /* validate ALL user-input */
fputs ("error: invalid number of rows.\n", stderr);
return NULL;
}
fputs ("enter number of cols: ", stdout);
if (scanf ("%d", n) != 1) {
fputs ("error: invalid number of cols.\n", stderr);
return NULL;
}
return create_matrix (*m, *n);
}
void prnt_matrix (int **matrix, int m, int n)
{
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++)
printf (" %4d", matrix[i][j]);
putchar ('\n');
}
}
void free_matrix (int **matrix, int m)
{
for (int i = 0; i < m; i++)
free (matrix[i]); /* free integers */
free (matrix); /* free pointers */
}
int main (void) {
int **matrix, m = 0, n = 0;
if ((matrix = obtn_matrix (&m, &n)) == NULL)
return 1;
prnt_matrix (matrix, m, n);
free_matrix (matrix, m);
return 0;
}
Since you "didn't share the filler function", the code above simply zeros all integer values by allocating the integers for each row with calloc instead of malloc which is a good idea when working with simulated arrays so that if you inadvertently fail to initialize one of the integers, you don't SegFault when you attempt to traverse all elements to, e.g. prnt_matrix, etc...
Example Use/Output
$ ./bin/matrix_cr_obtn
enter number of rows: 5
enter number of cols: 3
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
Memory Use/Error Check
In any code you write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.
It is imperative that you use a memory error checking program to insure you do not attempt to access memory or write beyond/outside the bounds of your allocated block, attempt to read or base a conditional jump on an uninitialized value, and finally, to confirm that you free all the memory you have allocated.
For Linux valgrind is the normal choice. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.
$ valgrind ./bin/matrix_cr_obtn
==10251== Memcheck, a memory error detector
==10251== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==10251== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==10251== Command: ./bin/matrix_cr_obtn
==10251==
enter number of rows: 5
enter number of cols: 3
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
==10251==
==10251== HEAP SUMMARY:
==10251== in use at exit: 0 bytes in 0 blocks
==10251== total heap usage: 6 allocs, 6 frees, 100 bytes allocated
==10251==
==10251== All heap blocks were freed -- no leaks are possible
==10251==
==10251== For counts of detected and suppressed errors, rerun with: -v
==10251== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Always confirm that you have freed all memory you have allocated and that there are no memory errors.
Look things over and let me know if you have further questions.

Converting a 2D array into a dynamic array causes core dump

I have a perfectly working code with 2D array of a float variable, vxy, in C language. The size of row (rrow) is being calculated inside the code - column (ccol) size is already known. So I tried converting using code fragments in this forum and both causes segmentation fault. The two codes are i) Bryan's method from how to allocate memory dynamically for a two dimensional array and ii) Using pointer to a pointer method from http://www.geeksforgeeks.org/dynamically-allocate-2d-array-c/. I chose these methods as the code is already functional with a 2D array so the rest of the code will survive this change.
static float vxy[5000][ccol] ;
vxy[r][c] = ...
The original 2D declaration and usage is above:
#include <stdlib.h>
int main(void)
{
int num_row = 3, num_col = 2, r;
int ** A;
A = malloc(num_row*(sizeof(*A)+num_col*sizeof(**A)));
for (r = 0; r < num_row; r++)
{
A[r] = (int*)(A+num_row)+r*num_col;
}
/* Accessing element at row r and column c is through:
*
* A[r][c].
*/
free(A);
return 0;
}
My implementation based on the above is:
int r;
float ** vxy;
vxy = malloc(rrow*(sizeof(*vxy)+ ccol*sizeof(**vxy)));
for (r = 0; r < rrow; r++) {
vxy[r] = (float*)(vxy + rrow) + r*ccol;
}
The second method is:
float **vxy = (float **)malloc(rrow * sizeof(float *));
for (i=0; i<rrow; i++)
vxy[i] = (float *)malloc(ccol * sizeof(float));
I updated the above 2nd method with the following - I got "Program received signal SIGSEGV, Segmentation fault" on the line of vxy[i] = malloc(ccol * sizeof(float));
float **vxy = malloc(rrow * sizeof(float *));
if (vxy = NULL) {
printf ("Memory allocation error.\n");
// return NULL;
}
for (i = 0; i < rrow; i++)
vxy[i] = malloc(ccol * sizeof(float));
What seems to going wrong with my implementation?
Update: I updated the full code from the source for the method one. I also want to know how to free the allocation and address failed malloc situations.
I'm sorry you are having difficulty with your 2D allocation, it really isn't too difficult. To dynamically allocate and access your elements with array[x][y] notation, you need to allocate x pointers to an array of float's (your rows), then allocate an y arrays of float's (your elements/columns) for each row. (no different than allocating an array of pointers to strings to hold lines of text)
An example of a simple allocation/initialization function with calloc (with m rows and n columns) shown without error checking on allocation is:
float **mtrx_calloc (size_t m, size_t n)
{
register size_t i;
float **array = calloc (m, sizeof *array);
for (i = 0; i < m; i++)
{
array [i] = calloc (n, sizeof **array);
}
return array;
}
To allocate a 3x4 matrix, you would use it like this:
float **matrix = mtrx_calloc (3, 4);
You can then manipulate the matrix as you like accessing all elements with matrix[x][y] notation. Also note the use of size_t instead of int. Your rows and columns and iterator will never be negative, so choosing size_t or unsigned type makes more sense.
Sometimes rather than looking at pieces of code, it is good to have a working example. I put together a short working example to help you along that includes all points we have discussed so far in the comments and above. It includes error checking on memory allocation omitted above. If you have any questions, just drop a comment.
#include <stdio.h>
#include <stdlib.h>
float **mtrx_calloc (size_t m, size_t n); /* initialize elements to 0 */
void mtrx_prn (size_t m, size_t n, float **matrix); /* print matrix with/pad */
void mtrx_free (size_t m, float **matrix); /* free memory allocated */
int main (void)
{
/* allocate the 3x4 matrix */
float **matrix = mtrx_calloc (3, 4);
/* fill with misc values */
register size_t i = 0, j = 0;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 4; j++)
matrix [i][j] = (float)(i + j);
}
/* print matrix */
printf ("\nThe dynamically allocated 3x4 matrix is:\n\n");
mtrx_prn (3, 4, matrix);
/* free memory alocated */
mtrx_free (3, matrix);
/* just to make it look pretty */
printf ("\n");
return 0;
}
/* allocate/initialize mxn matrix */
float **mtrx_calloc (size_t m, size_t n)
{
register size_t i;
float **array = calloc (m, sizeof *array);
if (!array) { /* validate allocation */
fprintf (stderr, "%s() error: memory allocation failed.\n", __func__);
exit (EXIT_FAILURE);
}
for (i = 0; i < m; i++)
{
array[i] = calloc (n, sizeof **array);
if (!array[i]) { /* validate allocation */
fprintf (stderr, "%s() error: memory allocation failed.\n", __func__);
exit (EXIT_FAILURE);
}
}
return array;
}
/* print a (m x n) matrix (check pad alloc) */
void mtrx_prn (size_t m, size_t n, float **matrix)
{
register size_t i, j;
for (i = 0; i < m; i++)
{
char *pad = "[ ";
for (j = 0; j < n; j++)
{
printf ("%s%6.3f", pad, matrix [i][j]);
pad = ", ";
}
printf ("%s", " ]\n");
}
}
void mtrx_free (size_t m, float **matrix)
{
register size_t i;
for (i = 0; i < m; i++)
{
free (matrix [i]);
}
free (matrix);
}
Output
(note: the fill with misc values equation was changed to prevent overflow on entry of large m x n, so output values will differ from below)
$ ./bin/mtrx_dyn_example
The dynamically allocated 3x4 matrix is:
[ 1.900, 2.800, 3.700, 4.600 ]
[ 2.800, 3.700, 4.600, 5.500 ]
[ 3.700, 4.600, 5.500, 6.400 ]
Leak Check with valgrind
When you are creating/allocating blocks of memory dynamically, you are responsible to tracking what you have allocated, preserving the starting address for the block of memory, and freeing the block of memory when you no longer need it. A great tool to help you check your memory use is a memory checker such as valgrind. (similar tools are available for all platforms). Simple to use, just valgrind ./progname. It will confirm for you whether any blocks remain unfreed and whether there are any access errors regarding your allocated blocks:
$ valgrind ./bin/mtrx_dyn_example
==15800== Memcheck, a memory error detector
==15800== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==15800== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==15800== Command: ./bin/mtrx_dyn_example
==15800==
The dynamically allocated 3x4 matrix is:
[ 1.900, 2.800, 3.700, 4.600 ]
[ 2.800, 3.700, 4.600, 5.500 ]
[ 3.700, 4.600, 5.500, 6.400 ]
==15800==
==15800== HEAP SUMMARY:
==15800== in use at exit: 0 bytes in 0 blocks
==15800== total heap usage: 4 allocs, 4 frees, 72 bytes allocated
==15800==
==15800== All heap blocks were freed -- no leaks are possible
==15800==
==15800== For counts of detected and suppressed errors, rerun with: -v
==15800== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
The problem is with the interplay between pointer to floats and actual floats, as mentioned in referenced answers, try to remove the type-casting and see what you get.
Both methods are valid (but accessed in different ways), there is also a first method which creates a 1-d array which represents a 2d array (thus accessed as a[i+j*r]), while the (first and) second methods actually allocates a 2-d array (accessed as a[i][j]).
try to use calloc as well if this helps, although malloc should be fine
Also try to fix your indices correctly (in the loops) when using either method to make sure you dont access memory out-of-bounds in the allocated array

memcpy on two-dimensional array

I am wondering if I am using the memcpy function right.
So I have a two-dim. array of strings, and when I try to fill them valgrind tells me
==825== Invalid write of size 8
==825== at 0x344B8E: _platform_memmove$VARIANT$Unknown (in /usr/lib/system/libsystem_platform.dylib)
==825== by 0x1C4D74: __memcpy_chk (in /usr/lib/system/libsystem_c.dylib)
==825== by 0x100001328: generate_test_data (check_generate_test_data.c:4120)
==825== by 0x100000CA6: main (check_generate_test_data.c:137)
==825== Address 0x100030a00 is 0 bytes after a block of size 32 alloc'd
==825== at 0x47F1: malloc (vg_replace_malloc.c:302)
==825== by 0x100000FBB: generate_test_data (check_generate_test_data.c:4095)
==825== by 0x100000CA6: main (check_generate_test_data.c:137)
int i;
char **test;
int total = 4;
int elements = 11;
test = malloc(sizeof(char**)* total);
for (i=0; i < total; i++) {
// char *to_fill --//is filled with a method
//
test[i] = malloc(sizeof(char*) * elements; // <== here is where compiler complains
memcpy(&test[i], &to_fill, strlen(to_fill); // <== here is where valgrind complains
}
When I change it to:
&test[i][0]
then the strings in test stay empty :S.. I also tried to remove the & of to_fill but with this my program just crashes.. I have no Idea what I am doing wrong here.
I changed all of the suggestions but the same error of valgrind appears, I even tried to put a constant char array into to_fill but still:
int i;
char **test;
char *to_fill;
int total = 4;
int elements = 11;
test = malloc(sizeof(char*)* total);
to_fill = malloc(sizeof(char)* 100);
to_fill[0] = '\0';
for (i=0; i < total; i++) {
//to_fill = method_to_fill_it();
strncpy(to_fill, "example", 7);
to_fill[7] = '\0';
test[i] = malloc(sizeof(char*) * elements;
memcpy(&test[i], &to_fill, strlen(to_fill); // <== here is where valgrind complains
to_fill[0] = '\0';
}
Your memcpy statement is wrong, you don't need to dereference a char pointer which holds the address as it's value. Do this instead:
memcpy(test[i], to_fill, strlen(to_fill));
When you do:
memcpy(test[i], &to_fill, strlen(to_fill));
the memory address where to_fill is stored is passed to the function.
What you want to pass is the memory to which to_fill, the pointer, points to.

Resources