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
Related
Hello I am new to C and I need someone to explain concepts to me. I am a JAVA programmer and I am trying to write a program in C. My current issue is trying to initialize an array with an unknown number. I know in C an array has to be initialized with a number instead of a variable like you can in Java. My question is if I can do this in Java:
int i = 0;
char array [i];
void f(){
\\some code
i++;
}
How can I do this in C? I'm trying to fill an array with certain strings that I get from a file. I don't know how many I will be getting from the file however. I have tried reading about malloc but in one tutorial it says:
int *pointer;
pointer=malloc(2*sizeof(int));
is equivalent to
int array[2];
But I'm looking for a way to do this while increment the array.
First to mention, malloc() and family is used for dynamic (runtime) memory allocation whereas int arr[2] usually denotes compile time memory allocation. They are not exactly equivalent.
However, if you want to resize the allocated memory on-the-fly, you're on right track. What you need to do next is to use realloc() to re-size the previously allocated memory location.
You can read the man page for more details.
Also, while using dynamic memory in C, you need to keep in mid that there is no garbage collector in C. You need to free() up every bit of memory allocated by you.
I know in C an array has to be initialized with a number instead of a variable like you can in Java
In C99 and beyond, variable initiated arrays are available.
My current issue is trying to initialize an array with an unknown number.
and:
But I'm looking for a way to do this while increment the array.
If you have an unknown number of elements at run-time, you can write a function to create (and free) memory, passing the relevant arguments as you need them. Here is an example of a function to create (and free) a 2 dimensional array of ints:
int ** Create2Dint(int **arr, int cols, int rows)
{
int space = cols*rows;
int y;
arr = calloc(space, sizeof(int));
for(y=0;y<cols;y++)
{
arr[y] = calloc(rows, sizeof(int));
}
return arr;
}
void free2DInt(int **arr, int cols)
{
int i;
for(i=0;i<cols; i++)
if(arr[i]) free(arr[i]);
free(arr);
}
If, during execution, you need to change the allocation of memory (change the size of the array) you can use realloc(), implemented here in similar fashion:
int ** Realloc2D(int **arr, int cols, int rows)
{
int space = cols*rows;
int y;
arr = realloc(arr, space*sizeof(int));
for(y=0;y<cols;y++)
{
arr[y] = calloc(rows, sizeof(int));
}
return arr;
}
Usage example:
(execute with two integer command line arguments, both > 0)
int main(int argc, char *argv[])
{
int **array = {0};
int cols, rows;
cols = atoi(argv[1]);
rows = atoi(argv[2]);
array = Create2Dint(array, cols, rows);
//Do stuff here to use array
//Memory requirements change during runtime:
cols += 20;
rows += 50;
array = Realloc2D(array, cols, rows);
//use array again...
//When you are finished with the memory, free it:
free2DInt(array, cols);
return 0;
}
I'm working on a basic shell (as in the console program that awaits commands and executes them in UNIX systems) replica in C, and need to be able to manipulate 2d arrays of char to store the environment variables.
I wrote a small function to create that 2d array and initialize each string to NULL before I fill it up elsewhere in my code.
Except that it crashes as soon as the program is launched, for some reason.
I have similar issues (namely occasional segfaults, probably due to me reading/writing in an inapropriate place) with two other functions, respectively to free those 2d arrays when needed, and to get the length of one of those 2d array.
If I don't use these two functions and malloc the 2d array within the rest of my code, without initializing anything except the last entry to NULL, but instead copy the env strings directly after the malloc, I have something that works. But it'd be better to be able to prevent the memory leaks, and to have that ft_tabnew function to work so that I could reuse it in future projects.
char **ft_tabnew(size_t size)
{
char **mem;
size_t i;
if (!(mem = (char **)malloc(size + 1)))
return (NULL);
i = 0;
while (i < size + 1)
{
mem[i] = NULL;
i++;
}
return (mem);
}
void ft_tabdel(char ***as)
{
int i;
int len;
if (as == NULL)
return ;
i = 0;
len = ft_tablen(*as);
while (i < len)
{
if (*as[i])
ft_strdel(&(*as[i]));
i++;
}
free(*as);
*as = NULL;
return ;
}
size_t ft_tablen(char **tab)
{
size_t i;
i = 0;
while (tab[i])
i++;
return (i);
}
NOTE : The ft_strdel function used in ft_tabdel is freeing a string that was dynamically allocated, and sets the pointer to NULL. I've been using it for a few months in several projects and it has not failed me yet.
Hopefully, you wonderful people will be able to tell me what misconception or misunderstanding I have about 2d arrays of chars, or what stupid error I'm making here.
Thank you.
You're not allocating enough space.
if (!(mem = (char **)malloc(size + 1)))
only allocates size+1 bytes. But you need to allocate space for size+1 pointers, and pointers are typically 4 bytes. You need to multiply the number of elements by the size of each element:
if (!(mem = malloc((size + 1) * sizeof(*mem))))
In the code
char **mem;
while (i < size + 1)
{
mem[i] = NULL;
i++;
}
mem is a "pointer to a pointer to a char" and hence its size is that of a pointer, not of a char. When you say mem[i] and incement i, you increment with the size of pointer, not of char, and so overwrite memory outside your allocated memory. Try:
if (!(mem = (char **)malloc((size + 1)*sizeof(void *))))
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.
I am trying to make a generic function in C that takes a 2D array of ANY type and copies it into a contiguous memory block. ( I need this function for Aggregate operations on MPI on my complex datatypes).
Imagine I have the following integer array
int n = 5;
int m = 6;
int** int_array = (int**) malloc(n* sizeof(int*));
for (int i = 0; i < n; i++ )
int_array[i] = (int *) malloc(m * sizeof(int) );
In this type of memory allocation one cannot, in principle, hope to access the , say i,j-th entry of int_array using the following pointer arithmetics
int value = (*lcc)[i*m+j];
Therefore I implemented a function that basically allocates a new memory block and neatly orders the entries of int_array so that the above indexing should work.
void linearize(char*** array, int n, int m,unsigned int size_bytes){
char* newarray = (char*)malloc(m*n*size_bytes);
//copy array!
for (int i = 0;i<n;i++)
for(int j = 0;j<m*size_bytes;j++)
{
newarray[i*m*size_bytes+j] = (*array)[i][j];
}
//swap pointers and free old memory!
for (int i = 0;i<n;i++)
{
char * temp = (*array)[i];
(*array)[i] = newarray + i*m*size_bytes ;
free(temp);
}
}
I wanted to make the above function to work with any kind of array type, hence I used char pointers to do operations byte by byte. I tested the function and so far it works, but I am not sure about memory deallocation.
Does free(temp) free the whole memory pointed to by int_array[i], that is the m*sizeof(int) bytes accessible from int_array[i] or only the first m bytes (since it thinks that our array is of type char rather than in) ? Or simply put, "Does the linearize function induce any memory leaks? "
Thank you in advance!
*EDIT*
As suggested by Nicolas Barbey, I ran a valgrind checks for memory leaks and it found none.
So to summarize the main points that I found difficult to understand about the behaviour of the program were:
in the function linearize does the following code induce memory leaks:
char * temp = (*array)[i];
(*array)[i] = newarray + i*m*size_bytes ;
free(temp);
NO!! somehow gnu compiler is smart enough to know how many bytes pointed to by "temp" to free. Originally I was afraid that if I array[i] is a pointer of type int , for example, that points to a memory location with say 5 ints = 5*4 bytes, the free(temp) is going to free only the first five bytes of that memory.
Another point to make is : how to free the already linearized array? that is if you have:
// first initialize the array.
int** array = (int**)malloc(5*sizeof(int*);
for(int i = 0; i< 5;i++)
array[i] = ( int* ) malloc(5*sizeof(int));
//now a call to linearize
linearize(&array,5,5,sizeof(int));
... do some work with array ....
// now time to free array
free(array[0]);
free(array);
//suffices to free all memory pointed to by array[i] and as well as the memory allocated
// for the pointers.
Thanks for the discussion and the suggestions.
You need to call free() exactly one call per malloc() inorder to be no memory leaks. Which means in your case int_array is passed to linearize function allocates a block of memory other than int_array allocation, therefore you need to loop over int_array[i] freeing each int* that you traverse followed by free'ing int_array itself. Also you need to free block created in linearize function too.
Here is a slightly slimmer version using actual two dimensional arrays:
void * linearize(void** array, int n, int m,unsigned int size_bytes){
char (*newarray)[m * size_bytes] = malloc(m*n*size_bytes);
//copy array!
int i;
for (i = 0;i<n;i++) {
memcpy(newarray[i], array[i], sizeof(*newarray));
free(array[i]);
}
free(array);
return newarray;
}
Use:
int (*newarray)[m] = linearize(array, n, m, sizeof(**int_array));
int value = newarray[i][j];
// or
value = newarray[0][i*m + j];
// or
value = ((int *)newarray)[i*m + j];
In my C code I am allocating memory for 2d array double E[2000][2000]; but when I run it gets a runtime error Segmentation fault(core dumped) and when I reduce the array size to somewhere around 900 then the code runs fine.
Why it is showing runtime error since double take 64 bits memory (IEEE standard) so the code should take approximately 32MB which is not much compared to the ram size.And if it is not supported in C then how should I proceed if my maximum number of data that I have to store is 4000000 each are floating point numbers.
Are you declaring E as a local variable ? If so, you're running out of stack memory.
void func()
{
double E[2000][2000]; /// definitely an overflow
}
Use dynamic allocation:
double* E = malloc(2000 * 2000 * sizeof(double));
/// don't forget to "free(E);" later
Or if you need the 2D array, use a zig-zag:
double** E = malloc(2000 * sizeof(double*));
/* check that the memory is allocated */
if(!E)
{
/* do something like exit(some_error_code); to terminate your program*/
}
for(i = 0 ; i < 2000 ; i)
{
E[i] = malloc(2000 * sizeof(double));
/* check that the memory for this row is allocated */
if(!E[i])
{
/* do something like exit(some_error_code); to terminate your program*/
}
}
Then the deallocation is a little more complicated:
for(i = 0 ; i < 2000 ; i)
{
free(E[i]);
}
free(E);
P.S. If you want to keep all of you data in a continuous way, there's a trick (code from Takuya Ooura's FFT Package)
double **alloc_2d(int n1, int n2)
{
double **ii, *i;
int j;
/* pointers to rows */
ii = (double **) malloc(sizeof(double *) * n1);
/* some error checking */
alloc_error_check(ii);
/* one big memory block */
i = (double *) malloc(sizeof(double) * n1 * n2);
/* some error checking */
alloc_error_check(i);
ii[0] = i;
for (j = 1; j < n1; j++) {
ii[j] = ii[j - 1] + n2;
}
return ii;
}
void free_2d(double **ii)
{
free(ii[0]);
free(ii);
}
The you just call
double** E = alloc2d(2000, 2000);
and
free_2d(E);
I assume you are allocating it on the stack by simply
double E[2000][2000];
which will probably be more than stack size allocated to your program.
Try using malloc (or new in c++) or increase the default stack size of your program using options. gcc can be configured using setrlimit() for this purpose.
setting stack size in gcc
Keep in mind that even if stack size is increased, an array of this size should be global
You can also use a single statement to allocate a 2D array on heap if one dimension is fixed in size
double (* E)[COLUMN_SIZE];
int rows = 20; // this is dynamic and can be input from user at run time
E = malloc(rows * sizeof(*E)); // this needs to be freed latter
A more detailed similar example
allocating 2d array without loops
It depends on where you allocate the array. Using stack space will probably cause an overflow (unless you get the linker to allocate an extra large stack).
For example, this might not work
int main()
{
double E[2000][2000]; // Likely an overflow
}
However, moving the array to the static memory area
double E[2000][2000];
int main()
{
// use E here
}
will probably avoid the problem.