In my program I have a structure that looks like this:
struct structure {
int n;
int *arr;
};
And I allocate memory for arr like this:
structure->arr = malloc(sizeof(int) * arr_size);
Now here is where I start to get confused, and I am not sure if I am doing it right. What I want to do is use "arr" as an array to store or access integers. So I set arr to point to an array that I created and filled with 0's:
int new_arr[i];
structure.arr = new_arr;
I am not sure if this is right, but so far I don't get any errors. So I create another array that stores these structures, and I insert some new structures in it. But when I try to free the member arr from any of the structures inside the array (like this free(&array_of_struct[i].arr);) I get an error:
==747==ERROR: AddressSanitizer: attempting free on address which was not malloc()-ed: 0x7fffd7c6ad08 in thread T0
SUMMARY: AddressSanitizer: bad-free (/lib/x86_64-linux-gnu/libasan.so.5+0x10d7cf) in __interceptor_free
==747==ABORTING
So I think I understand what the problem is, but I have no idea how to solve it. I don't imagine this is the way I'm supposed to point to an array, so can anyone tell me how to do it right?
UPDATE
So instead of writing "structure.arr = new_arr" I am now using memset this way:
memset(structure.arr, '\0', array_size * sizeof(int));
But I still get the same arror when trying to free structure.arr. Also if I try to use mempcy. Could there be something wrong with free(&array_of_struct[i].arr)?
UPDATE2
So I actually managed to use mempcy and free member "arr". The problem is, that I can only do it before I append the structure to my array of structures. If I try to free it after that (as a member of the array) I get the errors.
LAST UPDATE
I have managed to make it work with memset. The problem was that I had to write free(array_of_struct[i].arr) instead of free(&array_of_struct[i].arr)
Thank you all for the help.
Don't do this:
structure.arr = new_arr;
That's not a copy of array content. That simply reassigns the pointer.
That means you are replacing the pointer with an allocation from somewhere else. At best, you'll have a memory leak from not freeing the original allocation. At worst, you'll crash because you attempt to free new_arr which is a stack array (invalid to invoke free on that address).
Do this instead, copy the array contents instead of overwriting the pointer:
memcpy(structure.arr, new_arr, arr_size * sizeof(int));
But if you just want to "zero out" the original allocation (as you implied), you just need to do this:
memset(structure.arr, '\0', arr_size * sizeof(int));
Or just use calloc instead of malloc to allocate and zero-out the contents at the same time.
structure->arr = calloc(arr_size, sizeof(int));
Update
But I still get the same arror when trying to free structure.arr. Also if I try to use mempcy. Could there be something wrong with free(&array_of_struct[i].arr)?
You need to pass to free exactly what was assigned from malloc.
So instead of this:
free(&array_of_struct[i].arr);
This:
free(array_of_struct[i].arr);
int *p = malloc(size);
int arr[size];
p = arr; // Not good. The memory we allocated above is now lost.
free(?); // We don't have a pointer to the allocated memory
int *p = malloc(size);
int arr[size];
int *q = arr;
p = arr; // Ok, because we have saved the pointer so we can free later
free(q);
int *p = malloc(size);
int arr[size];
memcpy(p, arr, size * sizeof *p);
free(p); // Works fine. We have not overwritten the pointer
You get this error since you can free only memory that was malloc'd.
when you write int new_arr[SIZE] you allocate the array on the stack, so you don't need to free it (you can say it will be "freed" when you leave the function in which you allocated it).
As for your struct, if you're aiming for an array that has a constant size that you know in advance, I would recommend that you implement it like this:
struct my_struct {
int arr[SIZE];
}
This will allocate the array as part of the struct (in my opinion this is more readable). So when you define an instance of this struct in your program it's sufficient to write:
struct my_struct s;
and the array will be allocated as well. In this case, you won't need to free it since you won't malloc it.
If you don't know the size of the array in advance, then it would be better to first allocate the memory using malloc and then use memcpy like #selbie suggested.
Related
#include<stdlib.h>
#include <stdio.h>
#include <string.h>
struct t {
int value;
};
int main (void) {
struct t *a = malloc(6*sizeof(struct t));
struct t *b = malloc(sizeof(struct t));
struct t *c = malloc(sizeof(struct t));
c->value = 100;
struct t *d = malloc(sizeof(struct t));
d->value = 100;
struct t *e = malloc(sizeof(struct t));
e->value = 100;
memcpy(b, a, sizeof(*a));
int j = 0;
while (j<6){
a[j] = *c;
j++;
}
int t = 0;
while(t < 6){
free(&a[t]);
t++;
}
free(a);
}
I'm trying to free the elements inside the array one by one. But this code cannot run so I think there might something wrong with free inside the second while loop. After I changed the second while loop to:
while(t < 6){
printf("%d",a[t].value);
t++;
}
It will run. Any idea how can I free those elements?
Thanks!
I'm trying to free the elements inside the array one by one. But this code cannot run so I think there might something wrong with free inside the second while loop.
Yes, what's wrong is the attempt to free the elements one by one.
You cannot free allocated memory in different divisions than it was allocated in. The argument to free() must be a pointer value that was previously obtained from an allocation function (and not since freed). The free() call will then free the entire block. It cannot see any subdivisions of that block that you may be using, and it would be unlikely to be able to honor them even if it could see them.
Any idea how can I free those elements?
Free the whole block at once, after you're done with all the data within. That is, just
free(a);
(And also, free(b), free(c), etc.)
One free per malloc'd block.
When you malloc, you are not grabbing memory for each struct. You are grabbing one block (per malloc call) that happens to be large enough to fit 6 structs for a and 1 struct each for the others. You can only free each block of this block at once. In this case you should be freeing a through e (which are addresses returned by malloc assuming you had enough memory).
You could if you really needed to, malloc an array of struct * then malloc blocks into those struct *, but why would you in this case where the struct is small and easily copied?
The key is this: When you allocate a block of memory, malloc (calloc or realloc) will return a pointer to the beginning address in that block. 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. free() must be passed the same address returned by malloc().
You can not provide an address from the middle of the allocated block to free(). Why? Because that will not be an address originally returned by a previous call to malloc, calloc or realloc. That is a requirement, see the man-page for free() (man 3 malloc)
The free() function frees the memory space pointed to by ptr, which must have
been returned by a previous call to malloc(), calloc(), or realloc().
So you can only make a call to free() providing a pointer holding an address that was previously allocated and returned by malloc, calloc or realloc. In your case that is a, not &a[1] ... &a[5].
Strait to the point.
I have a struct with a string, char and int.
The struct is created dynamically because i will need it in different parts of my program.
struct A
{
char staticString[20];
char* dynamicString;
char character;
int integer;
};
I know if i want to create a struct i call:
A example = (A)malloc(sizeof(A));
In order to populate the dynamicString and int i used:
example->dynamicString = (char*)malloc(sizeof(char*));
example->integer = (int)malloc(sizeof(int));
Unfourtanetly when i tried to populate staticString and char it didn't worked.
Don't even ask what was my code for those, i tried a lot of combinations from everywhere.
In addition to that can somebody show me examples how to write/read those values?
Thanks in advance.
First things first:
You're using C, and by the way you've defined the structure, you need to declare the pointer like so:
struct A *example;
Next, malloc returns a pointer, so you need to cast to a pointer (and not to a structure):
(struct A *)malloc(sizeof(struct A));
Secondly, I'm not sure why but hey:
- you're trying to dynamically allocate an int in the structure. As I said previously, malloc returns a pointer, so in your structure you need an int pointer like so "int *integer;"
- you're trying to allocate a dynamic string, however you're not doing it properly, here is what I think you want
example->dynamicString = (char *)malloc(sizeof(char) * 10);
Where 10 is the size of your dynamic string.
Edit:
you may also populate the integer in your struct statically or dynamically, but I think you intended the static approach:
example->integer = 123;
The dynamic approach would be (assuming you have int *integer in your struct):
example->integer = (int *)malloc(sizeof(int));
*(example->integer) = 123;
Every time you create a new struct the memory in the heap is set to size of :
sizeof(char)*20 + sizeof(char pointer) +sizeof(char)+ sizeof(int).
If you want to save a string that will be pointed to by your char pointer- then you ask for allocation in heap for the size of that string- and malloc returns the pointer to that memory allocation on heap.
So, you already have a space for your char array, char pointer, char and int that was allocated when you asked to make a new struct and do not need to allocate it again.
also, keep in mind malloc returns a pointer to the allocated place on the heap- so if you malloc(sizeof(int)) you get a pointer to a memory allocation for an int on the heap- which is pointed to by a int pointer Not an int.
good luck!
I'm trying to declare and allocate memory for an array of structures defined as follows:
typedef struct y{
int count;
char *word;
} hstruct
What I have right now is:
hstruct *final_list;
final_list = calloc (MAX_STR, sizeof(hstruct));
MAX_STRbeing the max size of the char word selector.
I plan on being able to refer to the it as:
final_list[i].count, which would be an integer and
final_list[i].word, which would be a string.
ibeing an integer variable.
However, such expressions always return (null). I know I'm doing something wrong, but I don't know what. Any help would be appreciated. Thanks.
A struct that contains a pointer doesn't directly holds the data, but holds a pointer to the data. The memory for the pointer itself is correctly allocated through your calloc but it is just an address.
This means that is your duty to allocate it:
hstruct *final_list;
final_list = calloc(LIST_LENGTH, sizeof(hstruct));
for (int i = 0; i < LIST_LENGTH; ++i)
final_list[i].word = calloc(MAX_STR, sizeof(char));
This requires also to free the memory pointed by final_list[i].word before releasing the array of struct itself.
Lets say I have the following situation (some rough pseudocode):
struct {
int i;
} x
main(){
x** array = malloc(size of x pointer); // pointer to an array of pointers of type x
int* size = current size of x // (initally 0)
add(array, size);
}
add(x** array, int* size){ // adds one actual element to the array
x** temp = realloc(array, (*size)+1); // increase the array size by one
free(array);
array = temp;
// My question is targeted here
array[*size] = malloc(size of x); // makes a pointer to the value
array[*size]->i = size;
*size++;
}
My question is: Once add() is finished, do the values of the pointers stored in array disappear along with the function call stack, since I allocated them inside func()? I fear that they might, in which case would there be a better way for me to do things?
No, they don't. They persist until the pointer returned by malloc() is passed to the corresponding free() function. There would be no point in the existence of the malloc() function if it worked the same way as automatic arrays.
Edit: sidenote. As #Ancurio pointer it out, you're incorrectly freeing the memory behind the previous pointer returned by malloc() which is at that time invalid as realloc() has been used on it. Don't do that. realloc() does its job properly.)
I want to know how I can release a struct properly from memory and completely wipe it. I also need to wipe arrays or values within this struct. I tried just overwriting the struct with new data everytime the data changed but I observed a steady rise in memory use until I get a memory warning so I think my safest bet is to completely wipe the data first and then write to it again.
typedef struct {
SInt16 *array1;
SInt16 *array2;
} myStruct, *myStructPtr;
myStructArray myStruct[16];
for(int i=0;i<16;i++)
{
myStruct[i].array1 =
(AudioUnitSampleType *) calloc (asize, sizeof (SInt16));
myStruct[i].array2 =
(AudioUnitSampleType *) calloc (asize, sizeof (SInt16));
}
free(myStructArray) // throws SIGBART error
You didn't malloc or calloc myStructArray so you shouldn't free it. Loop over the elements and free myStruct[i].array1 and array2
for(int i=0;i<16;i++)
{
free(myStruct[i].array1);
free(myStruct[i].array2);
}
The general rule is simple - free what you malloc/calloc/realloc/strdup/other allocs, nothing more or less. Note that alloca is an exemption - it allocates on stack, so you should never free what you got from it.
myStructArray myStruct[16];
myStruct is an array of objects created on stack. You can not call free on it. free needs to be called on resources acquired from free store ( using malloc, realloc etc., ). Instead you need call free on struct members array1, array2.