I need your advice on this piece of code:
the table fields options[0], options[1] etc... doesn't seem to be freed correctly.
Thanks for your answers
int main()
{
....
char **options;
options = generate_fields(user_input);
for(i = 0; i < sizeof(options) / sizeof(options[0]); i++) {
free(options[i]);
options[i] = NULL;
}
free(options);
}
char ** generate_fields(char *)
{
char ** options = malloc(256*sizeof(char *));
...
return options;
}
The problem is this:
for(i = 0; i < sizeof(options) / sizeof(options[0]); i++)
options is a pointer type, not an array type, so sizeof(options) will always be the same (typically 4 bytes on a 32-bit machine or 8 bytes on a 64-bit machine), so sizeof(options)/sizeof(options[0]) will almost always be 1.
The key is to always free memory in the same manner as you malloc'ed it. So, if you malloc a 2-dimensional array and then malloc a series of 1-dimensional arrays, you need to do the reverse when freeing it:
char ** generate_fields(char *)
{
char ** options = malloc(256*sizeof(char *));
for(int i = 0; i < 256; i++)
options[i] = malloc(some_size);
return options;
}
void free_fields(char ** options)
{
for(int i = 0; i < 256; i++)
free(options[i]);
free(options);
}
Note that if the size (256 in this case) is not a constant, you need to keep track of it yourself, since otherwise you have no way of knowing how many times to loop when freeing.
You should have the same number of frees as you have mallocs.
In your code you allocate the array of pointers, but you don't allocate any memory for the individual elements of the array to point to. But your freeing code is written as if you did.
I'm going to add to Adam's answer here, because this probably won't fit in a comment. Adam is completely right. I suspect your generate_fields function, however, perhaps actually gets input from the user, I'm not sure. In any case, there are two ways to approach this:
char ** generate_fields(char *, int num_fields, int size_of_field)
{
char ** options = malloc(num_fields*sizeof(char *));
for(int i = 0; i < num_fields; i++)
options[i] = malloc(size_of_field);
return options;
}
and a corresponding free function, which I'll leave out for brevity. You can see what's going on - we're passing in the number of fields and the field size. Change this around as you need. The other option is to have generate fields pass back to the routine it's called from the size of the array. I'd do something like this:
int generate_fields(char** options)
{
int num_fields = 0;
// somewhere here we get num_fields
options = malloc(num_fields*sizeof(char *));
for(int i = 0; i < num_fields; i++)
options[i] = malloc(size_of_field);
return num_fields;
}
And you call from main like this:
int main()
{
int sizeofarray = 0;
char** fields;
sizeofarray = generate_fields(fields);
Or if you dislike that notation, you can always stick to what you had:
char** generate_fields(int* size)
As the function prototype (return options this time and do size= somewhere in the code and call from main like this:
int sizeofarray = 0;
char** options;
options = generate_fields(&sizeofarray);
Hope that gives you some more ideas, Adam, feel free to edit any / all of this into your answer as appropriate, it comes from your answer anyway.
Related
I've a problem about deallocating memory using free() in C.
My program generates a random genealogic tree using a matrix. This matrix can be very huge depending on the number of family members. The program seemed to work fine until I decided to generate more than one tree. I noticed that generating about 100 trees causes my 8GB RAM to fill! I'm sure I can make a better code to reduce the demand of memory, but my problem remains.
I use free() to deallocate memory and there's no error. I installed Valgrind to se what's happening and it says that about 100 million byte per tree are definitely lost. This means that free() doesn't work fine. I don't now where is the problem. I link some functions that I think are correlated to the problem.
typedef struct{
int f_id;
char f_name[L_NAMES];
int generations;
int n_members;
type_people *members;
int_mtx *mtx;
}type_family;
The struct above is for the family.
typedef struct temp{
int p_id;
char name[L_NAMES];
char f_name[L_NAMES];
int generation;
int n_sons;
struct temp **sons;
int f_id;
int sex;
int age;
}type_people;
This is for the members.
typedef struct{
int i;
int j;
int **val;
}int_mtx;
And the matrix.
In the main i call the function to initialize the tree:
type_family *family_a;
family_a = malloc(sizeof(type_family));
family_a = init_family_n_gen(family_a, 6);
This is the frist part of init_family_n_gen():
type_family *init_family_n_gen(type_family *family, int n){
...
family->members = malloc(max_people * sizeof(type_people));
family->mtx = mtxcalloc(family->mtx, max_people, max_people - 1);
...
This code is for mtxcalloc that initializes the matrix:
int_mtx *mtxcalloc(int_mtx *mtx, int i, int j){
mtx = malloc(sizeof(int_mtx));
mtx->i = i;
mtx->j = j;
mtx->val = malloc(i * sizeof(int *));
for(int a = 0; a < i; a++){
mtx->val[a] = malloc(j * sizeof(int));
for(int b = 0; b < j; b++){
mtx->val[a][b] = 0;
}
}
return mtx;
}
And to conclude the code to deallocate the family:
void free_family(type_family *family){
for(int m = 0; m < family->n_members; m++){
if(family->members[m].n_sons != 0){
free(family->members[m].sons);
}
}
mtxfree(family->mtx);
free(family->members);
}
And the one to deallocate the matrix:
void mtxfree(int_mtx *mtx){
for(int i = 0; i < mtx->i; i++){
free(mtx->val[i]);
}
free(mtx->val);
free(mtx);
}
Screen capture of Valgrind output
So I call the free_family(family_a) every time i need to regenerate the family but the memory still increases. (In the photo above the number of byte become 1 billion if i regenerate the family for 50 times).
Thanks for the support!
EDITED
I made a minimal reproducible example that emulates my original code. The structs and variables are the same but I changed the functions according to Weather Vane: they are all void and I pass them the double **.
The init_family_n_gen becomes:
void init_family(type_family **f){
type_family *family = malloc(sizeof(type_family));
family->members = malloc(100 * sizeof(type_people));
for(int m = 0; m < 100; m++){
family->members[m].n_sons = 0;
}
mtxcalloc(&family->mtx, 100, 99);
family->mtx->val[0][1] = 7;
family->mtx->val[9][8] = 1;
mtxrealloc(&family->mtx, 5, 4);
*f = family;
}
The main is:
type_family *family_a;
init_family(&family_a);
free_family(&family_a);
The only thing I added is this function(Is the code right?):
void mtxrealloc(int_mtx **mtx, int i, int j){
(*mtx)->i = i;
(*mtx)->j = j;
(*mtx)->val = realloc((*mtx)->val, (*mtx)->i * sizeof(int *));
for(int a = 0; a < (*mtx)->i; a++){
(*mtx)->val[a] = realloc((*mtx)->val[a], (*mtx)->j * sizeof(int));
}
}
I noticed that the problem occours when i use the realloc function and i can't figure why. I link the images of Valgrind with and without the function mtxrealloc. (I see that there is aslo a 48 byte leak...).
Valgrind with realloc
Valgrind without realloc
Thanks again for your support!
This:
init_family(&family_a);
Causes this code from mtxcalloc to execute:
mtx->val = malloc(i * sizeof(int *));
for(int a = 0; a < i; a++){
mtx->val[a] = malloc(j * sizeof(int));
for(int b = 0; b < j; b++){
mtx->val[a][b] = 0;
}
}
, with i, j = 100, 99. That is, you allocate space for 100 pointers, and for each one, you allocate space for 99 ints. These are then accessible via family_a->mtx.
Very shortly thereafter, you make this call:
mtxrealloc(&family->mtx, 5, 4);
, which does this, among other things:
(*mtx)->val = realloc((*mtx)->val, (*mtx)->i * sizeof(int *));
That loses all the pointers (*mtx)->val[5] through (*mtx)->val[99], each of which is the sole pointer to allocated space sufficient for 99 ints. Overall, sufficient space for 9405 ints is leaked before you even perform any computations with the object you are preparing.
It is unclear why you overallocate, just to immediately (attempt to) free the excess, but perhaps that's an artifact of your code simplification. It would be much better to come up with a way to determine how much space you need in advance, and then allocate only that much in the first place. But if you do need to reallocate this particular data, then you need to first free each of the (*mtx)->val[x] that will be lost. Of course, if you were going to reallocate larger, then you would need to allocate / reallocate all of the (*mtx)->val[x].
I am trying to learn how to create a function that will take a dynamic int array (int arrayPtr = (int) malloc...) and replace it with another dynamic array. This new array will not simply be of different values, but potentially a different number of elements.
From my research, I've learned that I need to pass into this function a reference to my array pointer, rather than the pointer itself (&arrayPtr). That means the function signature needs to have int **arrayPtr instead of int *arrayPtr.
I feel like it makes sense to me; We need to tell arrayPtr to point to a different location in memory, so we need the memory address of arrayPtr rather than its value (the memory address of the original array);
I wrote a little test program to see if I understood, but I cannot get it to work. Using debugging, I've observed the following: From within the function, the (int **arrayPtr) doesn't represent the entire array, but just the first element. That is, I can get the value 500 if I do *arrayPtr[0], but *arrayPtr[1] is inaccessible memory.
Here is my test program:
#include <stdlib.h>
void replaceArray(int **arrayPtr, unsigned int arrayLength) {
int i;
int *tempArrayPtr;
tempArrayPtr = (int *)malloc(sizeof(int) * arrayLength);
for (i = 0; i < arrayLength; ++i) {
tempArrayPtr[i] = *arrayPtr[i] * 2;
}
free(arrayPtr);
arrayPtr = &tempArrayPtr;
return;
}
int main(int argc, char **argv) {
int i;
int arrayLength = 2;
int *arrayPtr;
arrayPtr = (int*)malloc(sizeof(int) * arrayLength);
for (i = 0; i < arrayLength; ++i) {
arrayPtr[i] = i + 500;
}
replaceArray(&arrayPtr, arrayLength);
exit(EXIT_SUCCESS);
}
The function is supposed create a new array with the value of each element of the original array doubled, and have the arrayPtr variable in the calling function refer to the new array instead. As i have written it, however, it gets SIGSEGV when the replaceArray function tries to access *arrayPtr[1].
I realize that this little demonstration program is not doing anything that requires the behavior that I'm testing. It is just so that I can understand the concept with a simple example.
Since this is a tiny, trivial, program, I feel justified in that the answer that I accept will contain the complete working version of this code.
There have to be three changes in you code:
void replaceArray(int **arrayPtr, unsigned int arrayLength) {
int i;
int *tempArrayPtr;
tempArrayPtr = malloc(sizeof(int) * arrayLength);
for (i = 0; i < arrayLength; ++i) {
tempArrayPtr[i] = (*arrayPtr)[i] * 2;//In this if you use the without braces it will acts array of pointers that is pointing to a array. So we have to get the value from that using that braces.
}
free(*arrayPtr);//<< here we have to free the memory of arrayPtr not the address of the &arrayPtr.
*arrayPtr = tempArrayPtr; // Here you have to assign the address to that value of arrayPtr.
return;
}
There is no need the type cast the return value of malloc.
Both of these lines are wrong:
free(arrayPtr);
arrayPtr = &tempArrayPtr;
The first line passes the address of your variable to free(), rather than the address of the actual allocated array. Since the variable is on the stack rather than mallocated, free() will crash or abort here. What you want to do instead is free(*arrayPtr):.
The second line merely sets the local variable arrayPtr to the address of the variable tempArrayPtr. What you want to do instead is *arrayPtr = tempArrayPtr;.
See the below code and the inline comments.
#include <stdlib.h>
void replaceArray(int **arrayPtr, unsigned int arrayLength) {
int i;
int *tempArrayPtr;
tempArrayPtr = malloc(sizeof(int) * arrayLength); //do not cast
for (i = 0; i < arrayLength; ++i) {
tempArrayPtr[i] = (*arrayPtr)[i] * 2;
}
free(*arrayPtr); // free the *arrayPtr, [which is `arrayPtr` from `main`]
*arrayPtr = tempArrayPtr; //copy tempArrayPtr and put it into *arrayPtr
return;
}
int main(int argc, char **argv) {
int i;
int arrayLength = 2;
int *arrayPtr;
arrayPtr = malloc(sizeof(int) * arrayLength); // do not cast
for (i = 0; i < arrayLength; ++i) {
arrayPtr[i] = i + 500;
}
replaceArray(&arrayPtr, arrayLength);
exit(EXIT_SUCCESS);
}
I am trying to build two dimensional array by dynamically allocating. My question is that is it possible that its first dimension would take 100 values, then second dimension would take variable amount of values depending on my problem? If it is possible then how I would access it? How would I know the second dimension's boundary?
(See the comments in the code)
As a result you'll get an array such like the following:
// Create an array that will contain required variables of the required values
// which will help you to make each row of it's own lenght.
arrOfLengthOfRows[NUMBER_OF_ROWS] = {value_1, value_2, ..., value_theLast};
int **array;
array = malloc(N * sizeof(int *)); // `N` is the number of rows, as on the pic.
/*
if(array == NULL) {
printf("There is not enough memory.\n");
exit (EXIT_FAILURE);
}
*/
// Here we make each row of it's own, individual length.
for(i = 0; i < N; i++) {
array[i] = malloc(arrOfLengthOfRows[i] * sizeof(int));
/*
if(array[i] == NULL) {
printf("There is not enough memory.\n");
exit (EXIT_FAILURE);
}
*/
}
You can use array of 100 pointers:
int *arr[100];
then you can dynamically allocate memory to each of the 100 pointers separately of any size you want, however you have to remember how much memory (for each pointer) you have allocated, you cannot expect C compiler to remember it or tell it to you, i.e. sizeof will not work here.
To access any (allowed, within boundary) location you can simply use 2D array notation e.g. to access 5th location of memory allocated to 20th pointer you can use arr[20][5] or *(arr[20] + 5).
I believe the OP wants a single chunk of memory for the array, and is willing to fix one of the dimensions to get it. I frequently like to do this when coding in C as well.
We all used to be able to do double x[4][]; and the compiler would know what to do. But someone has apparently messed that up - maybe even for a good reason.
The following however still works and allows us to use large chunks of memory instead of having to do a lot of pointer management.
#include <stdio.h>
#include <stdlib.h>
// double x[4][];
struct foo {
double y[4];
} * x;
void
main(int ac, char * av[])
{
double * dp;
int max_x = 10;
int i;
x = calloc(max_x, sizeof(struct foo));
x[0].y[0] = 0.23;
x[0].y[1] = 0.45;
x[9].y[0] = 1.23;
x[9].y[1] = 1.45;
dp = x[9].y;
for (i = 0; i < 4; i++)
if (dp[i] > 0)
printf("%f\n", dp[i]);
}
The trick is to declare the fixed dimension in a struct. But keep in mind that the "first" dimension is the dynamic dimension and the "second" one is fixed. And this is the opposite of the old way ...
You will have to track the size of your dynamic dimension on your own - sizeof can't help you with that.
Using anonymous thingies you might even be able to git rid of 'y'.
Using a single pointer:
int *arr = (int *)malloc(r * c * sizeof(int));
/* how to access array elements */
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
*(arr + i*c + j) = ++count; //count initialized as, int count=0;
Using pointer to a pointer:
int **arr = (int **)malloc(r * sizeof(int *));
for (i=0; i<r; i++)
arr[i] = (int *)malloc(c * sizeof(int));
In this case you can access array elements same as you access statically allocated array.
I have this C function:
fill_array(&data, &size);
void fill_array(int **data, int *size){
printf("Size is:");
scanf("%d", size);
*data = malloc(*size * sizeof(int *));
int i = 0;
for (i = 0; i < size; i++){
(*data)[i] = rand() % 11;
}
}
I want to assign data[i] for example, to random number. How to do such a thing? I have tried many variations, but all of the time my program crashes.
Thanks.
*data = malloc(*size * sizeof(**data));
(*data)[5] = 15;
Refer to cdecl web site.
Do not cast malloc
Edit according to the question edit
the for loop contains typo
for (i = 0; i < size; i++)
it should be
for (i = 0; i < *size; i++)
you can use (*data)[5] = 15; instead of this *data[5] = 15; Because precedence of [] greater than precedence of *..
As others said, you need to put parentheses to get the operator precedence right. If you want to use the "array" a lot, it might make sense to create a temporary variable that is easy to use:
int *p;
...
*data = malloc(*size * sizeof **data);
p = *data;
And then you could use p[5] etc.
Good program design dictates that we should keep memory allocation and the actual algorithm separated. To have a function that takes user input and allocates memory and performs some algorithm is probably not the optimal program design.
So the proper solution is not to patch that function to make it work, but instead to make some new ones:
int get_size_from_user (void)
{
int size;
printf("Size is:");
scanf("%d", &size);
return size;
}
bool alloc_array (int** array, int size)
{
*array = malloc(size * sizeof(int));
return *array != NULL;
}
void fill_array (int* array, int size)
{
// ...whatever you want to do here
data[5] = 15;
}
And look at that, the need for obscure syntax disappeared as soon as we improved the program design! Coincidence?
I am still new with C and I am trying to empty a 2d char array. Here is the declaration:
char arg_array = (char**)calloc(strlen(buf), sizeof (char**));
for(i = 0; i<(strlen(buf)); i++)
{
arg_array[i] = (char*) calloc (strlen(buf), sizeof(char*));
}
Here is where I try to empty it:
void make_empty(char **arg_array)
{
int i;
for(i = 0; i <= BUFSIZ; i++)
{
arg_array[i][0] = '\0';
}
return;
}
Any help is appreciated
So, am I doing it right because this seems to give me segfaults when I try to add data to the array again and then print it?
Empty is just to have it empty - how can I explain more? lol
Try this:
void make_empty(char **arg_array, int rows, int cols)
{
int i,j;
for(i = 0; i <rows; i++)
{
for(j=0; j<cols;j++)
{
arg_array[i][j] = '\0';
}
}
return;
}
Where rows is number of rows and cols number of cols of your array.
P.S. This function clears the whole array as you should always do. As I commented before, putting '\0' as a first char in string does not clear the whole row, it only makes the rest of it ,,invisible'' for functions like printf. Check this link for more information: http://cplusplus.com/reference/clibrary/cstdio/printf/
There is no need to empty it. Often in C, memory allocation is done with malloc which simply returns to you a block of memory which is deemed owned by the caller. When calloc is called, as well as returning you a block of memory, the memory is guaranteed to be initialized to 0. This means for all intents and purposes it is already 'empty'.
Also I'm not quite sure if your code does what you are intending. Let me explain what it does at the moment:
char arg_array = (char**)calloc(strlen(buf), sizeof (char**));
This line is simply wrong. In C, there is no need to cast pointers returned from calloc because they are of type void *, which is implicitly casted to any other pointer type. In this case, you are storing it in a char type which makes no sense. If you do this:
char ** arg_array = calloc(strlen(buf), sizeof (char**));
Then it allocates an array of pointers of strlen(buf) length. So if buf is "hello" then you have now allocated an array which can store 5 pointers.
for(i = 0; i<(strlen(buf)); i++)
{
arg_array[i] = calloc (strlen(buf), sizeof(char*));
}
Again, I have removed the redundant cast. What this does is populates the array allocated earlier. Each index of the array now points to a char string of strlen(buf) * sizeof(char *) length. This is probably not what you want.
Your question is more clear to me now. It appears you want to remove the strings after populating them. You can do it two ways:
Either free each of the pointers and allocate more space later as you did before
Or set the first character of each of the strings to a null character
To free the pointers:
for(i = 0; i<(strlen(buf)); i++)
{
free(arg_array[i]);
}
To set the first character of each string to a null character:
for(i = 0; i<(strlen(buf)); i++)
{
arg_array[i][0] = '\0';
}
That is the same code as what you have originally and should be fine.
As proof, the following code will run without errors:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
char * buf = "hello";
char ** arg_array = calloc(strlen(buf), sizeof (char**));
unsigned int i;
for(i = 0; i < strlen(buf); i++) {
arg_array[i] = calloc(strlen(buf),
sizeof(char *));
}
for(i = 0; i < strlen(buf); i++) {
arg_array[i][0] = '\0';
}
for(i = 0; i < strlen(buf); i++) {
free(arg_array[i]);
}
free(arg_array);
return EXIT_SUCCESS;
}
If your code is segfaulting, the problem is coming from somewhere else. Did you overwrite the arg_array variable? Are you sure BUFSIZE is equal to strlen(buf)?