structs free up memory function - c - c

I have a program i made and its running perfectly! the only problem is the free pointers function
this is a link for the full code https://codeshare.io/aVE3n3
The problem is that i success to free the player name pointer, but after the program doesn't let me free the player's pointer.
I'd love to get some help, thanks.
void freeTeam(team* t,int size)
{
int temp;
for (int j = 0; j < size; j++)
{
temp = t[j].current_players;
for (int i = 0; i < temp; i++)
{
free(t->players[i].name);
}
free(t->players);
for (int i = 0; i < temp; i++)
{
free(t[i].team_name);
}
free(t[j]);
}
}

The first wrong part is
t->players = (player**)calloc(t->max_players, sizeof(player*));
in initTeam().
t->players has type player* and its element type is player.
In typical environment, player (one pointer and other elements) consume more memory than player* (one pointer), so you won't allocate enough memory here.
It should be
t->players = calloc(t->max_players, sizeof(player));
or
t->players = calloc(t->max_players, sizeof(*t->players));
(note: c - Do I cast the result of malloc? - Stack Overflow)
The second wrong part is the freeTeam function.
free(t->players[i].name); may cause double (or more) free because only t[0] is dealt with.
free(t[i].team_name); may cause double (or more) free and/or out-of-bounds read because the usage of loop is wrong.
free(t[j]); is invalid because structure is not a pointer.
It should be
void freeTeam(team* t,int size)
{
int temp;
for (int j = 0; j < size; j++)
{
temp = t[j].current_players;
for (int i = 0; i < temp; i++)
{
free(t[j].players[i].name);
}
free(t[j].players);
free(t[j].team_name);
}
}
after that, t should be freed after freeTeam(t,size); in main().
Additionaly, you should use standard int main(void) in hosted environment instead of void main(), which is illegal in C89 and implementation-defined in C99 or later, unless you have some special reason to use non-standard signature.

Related

Problem with free() function in C and memory-leaks

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].

Does this free() function clean the memory?

I need your help, becouse I dont know whether I realy free the allocated memory. I also will be very grateful, if you could advice me some tools for this purpose. Thanks!
P.S You can skip bb_sort and swap functions.
#include <stdio.h>
#include <stdlib.h>
typedef struct DArray{
double * array;
int size;
} DArray;
void getArrays(DArray * arrays, int numOfArrays){
int curArraySize, i;
while(numOfArrays >= 0){
printf("Input size of array: "); scanf("%d", &curArraySize);
if(arrays[numOfArrays].array = (double*)malloc((arrays[numOfArrays].size = curArraySize)*sizeof(double))){
for(i = 0; i < arrays[numOfArrays].size; ++i)
arrays[numOfArrays].array[i] = rand()%100;
--numOfArrays;
}
else{
printf("Error, have no enough memory in the system!"); break;
}
}
}
void swap(double * arr, int pos1, int pos2) {
int tmp = arr[pos1];
arr[pos1]=arr[pos2];
arr[pos2]=tmp;
}
double * bb_sort(double * arr, int size){
int i, j, noChanges = 1;
while(1){
for(i = 0;i < size;++i){
for(j = 0;j < size-1;++j){
if(arr[j] < arr[j+1]){
swap(arr, j, j+1);
noChanges = 0;
}
}
if(noChanges) return arr;
noChanges = 1;
}
}
}
int main() {
srand (time (NULL));
int numOfArrays, i, j;
printf("Input number of arrays: "); scanf("%d", &numOfArrays);
DArray arrays[numOfArrays];
getArrays(arrays ,numOfArrays-1);
for(i = 0; i < numOfArrays; ++i){
bb_sort(arrays[i].array, arrays[i].size);
}
for(i = numOfArrays-1; i >= 0; --i){
printf("\nSorted array num#%d\n", i+1);
for(j = 0; j < arrays[i].size; ++j)
printf(" %.1lf ", arrays[i].array[j]);
free(arrays[i].array); <------FREE MEMORY?
printf("\n");
}
printf("Done!");
while(1){
}
return 0;
}
=====================================================================================================
Short Answer:
The OP ask if 'memory is cleaned'. Technically, there is no requirement for the free implementation to CLEAN the memory (e.g, sets the data to zero, or some random data). Most implementation will not CLEAR to memory to save time.
If, by mistake, the code will try to read the data, it will usually find the data is still in memory, potentially modified by the free call, or by other code, which was assigned the freed memory to other tasks.
For security sensitive information (password, credit card numbers, private keys), it is common to ZERO the data, or to fill the region with other pattern, before calling free. It will make it harder/reduce the risk of the data being access by mistakes, bugs or hacking.
Some memory debuggers will fill freed memory with pattern data/guards/etc, to help detect memory problems earlier than later.
Yes it will, since your program created array pointer using malloc function, and it does not manipulate that pointer, according to C99 standard (ISO/IEC 9899:1999):
7.20.3.2 The free function (p: 313):
The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if the argument does not match a pointer earlier returned by the calloc, malloc, or realloc function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined.

When working with pointers in C, when and why do we need to use malloc?

/* Note: The returned array must be malloced,
assume caller calls free(). */
int* twoSum(int* nums, int numsSize, int target) {
int *ans; //why error
for(int i = 0; i < numsSize; i++){
for(int j = i+1; j < numsSize; j++){
if(nums[i] + nums[j] == target){
ans[0] = i;
ans[1] = j;
break;
}
}
}
return ans;
}
Why code above is incorrect and code below correct (with malloc added)?
/* Note: The returned array must be malloced,
assume caller calls free(). */
int* twoSum(int* nums, int numsSize, int target) {
int *ans = (int*)malloc(2*sizeof(int)); //why not error
for(int i = 0; i < numsSize; i++){
for(int j = i+1; j < numsSize; j++){
if(nums[i] + nums[j] == target){
ans[0] = i;
ans[1] = j;
break;
}
}
}
return ans;
}
If you don't assign anything to ans, it contains some garbage value. Attempting to dereference the pointer (i.e. access what the pointer points to), which using an array index is implicitly doing, means you're trying to read/write some arbitrary memory location you're not supposed to.
Trying to use an invalid pointer invokes undefined behavior. This means your program may crash, it may output strange results, or it may appear to work properly. Also, making a seemingly unrelated change such as an extra call to printf for debugging, adding an unused variable, or compiling with different optimization settings can change how undefined behavior manifests itself.
So just because the program seems to be behaving properly doesn't mean there isn't a problem. It just means it will probably show up later when you least expect it.
A pointer needs to point to some valid memory location before you can use it. Calling malloc allocates a block of memory and returns a pointer to that memory. After assigning that address to ans, you can then use it to read/write the memory that was allocated. This guarantees that your program will be well defined.

How should I free an array in C?

I created a function to free an array in C, but I don't know
whether it is correct or not:
void dealloc_array(void *array[], int size) {
int i = 0;
for (i = 0; i < size; i++) {
if (array[i]) free(array[i]);
}
if (array) free(array);
}
I'm not sure whether I should execute free(array) at the end. Technically, we've already freed all the array elements, so we don't need to do free(array).
Thanks for the help.
If you malloc the pointer as well as each element of the array you will need to free that pointer after your for loop.
For example:
int **array;
array = malloc(SIZE*sizeof(int*));
for(int ii = 0; ii < SIZE; ii++)
{
array[ii] = (int*)malloc(sizeof(int));
}
you will have to free each element and free array.
Essentially for every malloc/calloc you have, you must have a free
You must write free(array) at the end, otherwise there will be memory leak.

using malloc for block of structs

I am trying to allocate a block of memory, and store a list of structures without using multiple mallocs for each... this is just a generic example, I don't have the original code I was working with earlier, but this is the general idea, but my problem was that I was getting heap corruption when other parts of my code executed after the InitPoints() function call. I don't know what part of my code is illegal, but I suspect it is in the for loop of the InitPoints() function. I am trying to use this as table, then I can create additional tables of defined size if I ran out of memory and link them together... so kind of like a dynamic expanding array if that makes any sense.
typedef struct Tb{
POINT points;
POINT *next;
} TABLE;
typedef struct Pt{
int x;
int y;
}POINT;
POINT *mypoints;
int main() {
int size = 10;
int i = 0;
mypoints = InitPoints(size);
for(i=0; i < size; i++)
{
printf("mypoint [%d] = (%d,%d)\n",i, mypoints->x, mypoints->y);
mypoints = mypoints + sizeof(POINT);
}
// some other code...
// i.e. createThread(....)
return 0;
}
POINT* InitPoints(int size)
{
POINT *tmp;
POINT *orig;
int a = 10;
int b = 1000;
orig = (POINT*) malloc (sizeof(POINT) * size);
if(orig == NULL)
return NULL;
tmp = orig;
for (i = 0; i < size; i++)
{
tmp->x = a++;
tmp->y = b++;
tmp = tmp + sizeof(POINT);
}
return orig;
}
This is wrong:
mypoints = mypoints + sizeof(POINT);
You should review pointer arithmetic in C. Just use:
mypoints += 1; /* or something similar */
(There is a similar problem in your InitPoints function)
Here's one referemce:
http://www.eskimo.com/~scs/cclass/notes/sx10b.html
The problem is in this line:
tmp = tmp + sizeof(POINT);
It should be
++tmp;
The latter says to increment the pointer by one element; since it points to the structure, it increments by the size of the structure. The original code instead increments by n elements where n is the number of bytes in the structure. For example, if int is 32-bits, it will advanced by 8 elements.
This is why I would do it
for (i = 0; i < size; i++)
{
orig[i].x = a++;
orig[i].y = b++;
}
In C, adding an integer to a POINT* pointer advances the pointer not by that number of bytes, but by that number of POINT structures.
You have two places in your code where you add sizeof(POINT) to your pointer. Instead you should just add 1.

Resources