I am starting to learn dynamic memory allocation. In this code, I have created in main function 2d array:
int r, c;
scanf("%d %d\n", &r, &c);
size_t row = (size_t) r;
size_t col = (size_t) c;
int **board = malloc(row * sizeof(*board));
for (int i = 0; i < r; i++) {
board[i] = malloc(col * sizeof(*board[i]));
}
(I need both int and size_t because of for loops, especially when r>=0, which is always true for size_t).
Then I change the board with other functions. Valgrind returs:
==59075== 364 (56 direct, 308 indirect) bytes in 1 blocks are definitely lost in loss record 2 of 2
==59075== at 0x483577F: malloc (vg_replace_malloc.c:299)
==59075== by 0x10B4DB: main (name22.c:122)
==59075==
122 line is:
int **board = malloc(row*sizeof( *board));
I suppose I have to use free(), but after checking other answers I don't know, where is my mistake and where to put free(), if use use this table through the rest of the program. I would appreciate your hints and explanations.
`
When you call int **board = malloc(row * sizeof(*board)); , the system will allocate you row * sizeof(*board) bytes of memory and then return a pointer to the start of that memory (ie - a memory address), which you are storing in the int ** variable called board.
When your program finishes, the system will reclaim that memory, so if your program is short lived, it probably doesn't matter very much, but it's good practise to get into the habit of freeing your memory because it will not reclaim any memory at all until your program exits, unless you tell it to.
For that reason, you should always call free(...), passing in the memory address you were given when you first called malloc(...), once you are done with that memory. In most cases, each call to malloc(...) should have an equal and opposite call to free(...)
This is important because your system has a finite amount of memory. If your program is asking for resources and then never giving them back when they are done you will eventually run out of memory - this is what is called a "memory leak".
So for you, calling free(...) correctly, is going to look something like this:
int **board = malloc(row * sizeof(*board));
for (int i = 0; i < r; i++) {
board[i] = malloc(col * sizeof(*board[i]));
}
// Do something with board
for (int i = 0; i < r; i++) {
free(board[i]);
}
free(board);
Related
I was reading a textbook which describes a common mistake when dealing with dynanmic memory allocation, below is the buggy code:
int *heapref(int n, int m)
{
int i;
int *x, *y;
x = (int *)malloc(n * sizeof(int)); //line 6
.
. // Other calls to malloc and free
.
free(x); //line 10
y = (int *)Malloc(m * sizeof(int)); //line 12
for (i = 0; i < m; i++)
y[i] = x[i]++; /* Oops! x[i] is a word in a free block */
return y;
}
And the author says:
Depending on the pattern of malloc and free calls that occur between lines 6 and 10, when the program references x[i] in line 14, the array x might be part of some other allocated heap block and may have been overwritten
I'm a little bit confused here, the only thing that can cause issue to me is the line 12 which allocates a new memory block after free(x) , if I comment out line 12, then the program will still function correctly by luck, isn't it? How does malloc and free calls that occur between lines 6 and 10 affect sth that actually happen after itself?
In this code, while we are dynamically allocating memory for the 2D array, after 4 address why it is taking a gap of 16 bytes but when we are statically allocating 2D array then it does not have such gap.... what is the reason behind this???
#include <stdio.h>
#include <stdlib.h>
int main()
{
int r = 3, c = 4, i, j, count;
int stat[r][c];
int *arr[r];
for (i=0; i<r; i++)
arr[i] = (int *)malloc(c * sizeof(int));
// Note that arr[i][j] is same as *(*(arr+i)+j)
count = 0;
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
arr[i][j] = ++count; // Or *(*(arr+i)+j) = ++count
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
printf("%d\n", *(arr+i)+j);
printf("\n\n");
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
printf("%d\n", *(stat+i)+j);
/* Code for further processing and free the
dynamically allocated memory */
return 0;
}
Because you are not allocating a 2D array. You are allocating a set of 1D arrays, and those allocations do not have to be contiguous (most malloc implementations reserve some bytes to store the size of the allocated block).
To dynamically allocate a "true" 2D array where number of rows and columns aren't known until runtime, you'd do something like this:
stat (*arr)[c] = malloc( sizeof *arr * r );
that would be contiguous like any "normal" 2D array.
But...
Strictly speaking, this behavior is undefined - since arr points to a VLA, the sizeof *arr expression must be evaluated at runtime, not at compile time, and arr is not a valid pointer value at that point. I've never seen this fail on any implementation I've used, but that doesn't mean it won't fail somewhere. If c were constant instead, like
stat (*arr)[3] = malloc( sizeof *arr * r );
then there wouldn't be a problem, and this would be the preferred way to dynamically allocate an Nx3 array.
If you need all array elements to be contiguous (such that you could traverse the entire array with a pointer or something like that), then the safest option is to allocate your memory as a 1D array:
stat *arr = malloc( sizeof *arr * r * c );
and compute the offsets manually:
x = arr[ i * r + j ];
If you want the convenience of 2D notation, you could try creating a pointer and setting to point to the beginning of the array, something like
stat (*ptr)[c] = (stat (*)[c]) arr;
but that kind of pointer aliasing is also undefined if the pointer types are not compatible, and we've no reason to expect that a pointer to T is compatible with a pointer to an array of T.
The comments on your question have the most essential advice - don't worry about where malloc puts your memory. There is no assurance that it will be in any order. It may locate allocations in pursuit of various optimizations or speculations, and may vary from one execution to the next. If nothing else, other memory allocations, calls to free, garbage collection (in languages with GC, that is) between your calls to malloc will affect the location of the next allocation.
This can also vary with compiler, compiler options, OS, etc.
As for the specific reason your allocations have a 16 byte gap, that's impossible to say without more, and likely very deep, insight into your scenario. BTW, you didn't include output of your printf in your question.
But if I had to guess, I'd say the memory manager was aligning the allocations up with memory boundaries...perhaps a 32-byte or 64-byte boundary.
You're allocating 4 * sizeof(int). If an int is 4 bytes on your system, that's 16 bytes. If your malloc likes to line things up to 32 bytes, that might explain the 16-byte gaps you're seeing.
But again...this is just a guess. The simple answer is...you shouldn't care.
But if you DO care for some reason, you probably need to do your own allocation. malloc a much larger chunk of memory, and then manage your own pointers and allocations internally.
I am relatively new to C and have coded (or more precise: copied from here and adapted) the functions below. The first one takes a numpy array and converts it to a C int array:
int **pymatrix_to_CarrayptrsInt(PyArrayObject *arrayin) {
int **result, *array, *tmpResult;
int i, n, m, j;
n = arrayin->dimensions[0];
m = arrayin->dimensions[1];
result = ptrvectorInt(n, m);
array = (int *) arrayin->data; /* pointer to arrayin data as int */
for (i = 0; i < n; i++) {
result[i] = &array[i * m];
}
return result;
}
The second one is used within the first one to allocate the necessary memory of the row vectors:
int **ptrvectorInt(long dim1, long dim2) {
int **result, i;
result = malloc(dim1 * sizeof(int*));
for (i = 0; i < dim1; i++) {
if (!(result[i] = malloc(dim2 * sizeof(int)))){
printf("In **ptrvectorInt. Allocation of memory for int array failed.");
exit(0);
}
}
return result;
}
Up to this point everything works quite fine. Now I want to free the memory occupied by the C array. I have found multiple threads about how to do it, e.g. Allocate and free 2D array in C using void, C: Correctly freeing memory of a multi-dimensional array, or how to free c 2d array. Inspired by the respective answers I wrote my freeing function:
void free_CarrayptrsInt(int **ptr, int i) {
for (i -= 1; i >= 0; i--) {
free(ptr[i]);
}
free(ptr);
}
Nontheless, I found out that already the first call of free fails - no matter whether I let the for loop go down or up.
I looked for explenations for failing free commands: Can a call to free() in C ever fail? and free up on malloc fails. This suggests, that there may have been a problem already at the memory allocation. However, my program works completely as expected - except memory freeing. Printing the regarded array shows that everything should be fine. What could be the issue? And even more important: How can I properly free the array?
I work on a Win8 64 bit machine with Visual Studio 10 64bit compiler. I use C together with python 3.4 64bit.
Thanks for all help!
pymatrix_to_CarrayptrsInt() calls ptrvectorInt() and this allocation is made
if (!(result[i] = malloc(dim2 * sizeof(int)))){
then pymatrix_to_CarrayptrsInt() writes over that allocation with this assignment
result[i] = &array[i * m];
causing a memory leak. If array is free()'d then attempting to free() result will fail
I'd like to allocate memory for the 2d int ptr below, but I'm not 100% positive I've done it correctly, so any pointers (ha ha) on that would be great. Is the way I free the array and its indexes in the for loop correct? Also, what is the difference between the first malloc and the second malloc: (int *) and (int)?
int **array = NULL;
int mem_size = 0;
int i = 0, j = 0;
// leaving out how mem_size is calculated, but it can vary
array = malloc(sizeof(int *) * mem_size);
if (array == NULL) {
// some error message
return;
}
for (i = 0; i < mem_size; i++) {
array[i] = malloc(sizeof(int) * 2);
if (!(array[i])) {
// some error message
for (j = 0; j < i; j++)
free(array[j]);
free (array);
return;
}
}
This is only a section of the code I wrote. At the end, I am freeing the array:
for (i = 0; i < mem_size; i++)
free(array[i]);
free(array);
It is just a compile time constant - size of pointer in first case, size of int in second. It may vary between systems (e.g. if compiling for 32bit systems, pointer would be 4 bytes, while on 64bit systems it is 8 bytes).
In case any of the mallocs fail in the for loop, should I be freeing the array there
You should be freeing everything you've allocated so far - each array[0..(i-1)] and array itself.
malloc(sizeof(int *) * mem_size)
Allocates memory for array of mem_size pointers.
malloc(sizeof(int) * 2);
Allocates memory for 2 ints.
Also you should consider allocating ordinary 1D array and just calculating index when you want to access it.
sizeof(int) is equal to 4 bytes
sizeof(int *) is also equal to 4 bytes
... since a pointer only holds 4 bytes.
When you call malloc(int) and malloc(int *) - in both cases, the memory manager allocates 4 bytes on the heap and returns a pointer to the allocated memory.
Since you are going to store that address into the array (which is a double pointer and can thus only hold the address of another pointer), the following is illegal:
array = malloc(sizeof(int *) * mem_size); --- illegal to use
You may implement what you want in the following way:
int *ptr = NULL;
int **p_ptr = NULL;
ptr=(int *)malloc(sizeof(int *));
p_ptr = &ptr;
**p_ptr = 100 or any other value; now, whatever changes you made will be reflected in the allocated size of 4 bytes
Each one of them is determined according to a different characteristic within your platform.
The size of int is determined by the compiler, which is typically designated for a specific processor.
So it is effectively derived from the CPU architecture.
It is usually 4 bytes, but may be 2 bytes on some platforms.
The size of int* (or any other pointer) is determined by the size of the virtual memory address space.
So it is effectively derived from the MMU architecture.
It is 4 bytes on 32-bit systems and 8 bytes on 64-bit systems.
I wrote a C code that usea a matrix of double:
double y[LENGTH][4];
whith LENGTH=200000 I have no problem.
I have to increase the numbers of rows to LENGTH=1000000 but when I enter this value and execute the program it returns me segmentation fault.
I tried to allocate more memory using malloc:
double **y = (double **)malloc(LENGTH * sizeof(double*));
for(int i = 0; i < LENGTH; i++){
y[i] = (double *)malloc(4 * sizeof(double));
}
I run the the code above and after some second of calculations it still gives me "segmentation fault".
Could anyone help me?
If you want a dynamic allocated 2D array of the specified row-width, just do this:
double (*y)[4] = malloc(LENGTH * sizeof(*y));
There is no need to malloc each row in the matrix. A single malloc and free will suffice. Only if you need dynamic row width (each row can vary in width independent of others) or the column count is arbitrary should a nested malloc loop be considered. Neither appears to be your case here.
Notes:
Don't cast malloc in C programs
Be sure to free(y); when finished with this little tryst.
The reason your statically allocated array is segfaulting with a million elements is (presumably) because it's being allocated on the stack. To have your program have a larger stack, pass appropriate switches to your compiler.
ProTip: You will experience less memory fragmentation and better performance if you flip your loop around, allocating
(double *)malloc(LENGTH * sizeof(double));
four times. This will require changing the order of your indices.
I ran the the code with this definition and after some second of calculations it still gives me "segmentatin fault"
If you're getting a segmentation fault after allocating the memory, you're writing outside of your memory bounds.
I run this code
#include <stdio.h>
#include <stdlib.h>
// We return the pointer
int **get(int N, int M) /* Allocate the array */
{
/* Check if allocation succeeded. (check for NULL pointer) */
int i, **table;
table = malloc(N*sizeof(int *));
for(i = 0 ; i < N ; i++)
table[i] = malloc( M*sizeof(int) );
return table;
}
void free2Darray(int** p, int N) {
int i;
for(i = 0 ; i < N ; i++)
free(p[i]);
free(p);
}
int main(void)
{
const int LENGTH = 1000000;
int **p;
p = get(LENGTH, 4);
printf("ok\n");
free2Darray(p ,LENGTH);
printf("exiting ok\n");
return 0;
}
and it was executed normally.
I got the code from my pseudo-site.
You should not cast what malloc returns. Why?
Also notice, that since you need a dynamic allocation only for the number of rows, since you know the number of columns. So, you can modify the code yourself (so that you have some fun too. :) )
I hope you didn't forget to **free** your memory.