I'm pretty sure I'm doing nothing wrong, but thought I'd ask anyway.
We have:
struct some_struct **array_of_ptrs = calloc (num, sizeof (struct some_struct*));
Now assume I just point each of these pointers in the 'array' to a struct some_struct. Now surely to free up the memory, I just do:
free (array_of_ptrs);
Surely this is perfectly acceptable? The reason I ask is because I am doing something similar in my code and gdb is complaining of a free error.
This looks correct, as long as you realize that you're getting an array of pointers, not an array of structures, and you have to assign the pointers yourself. It sounds like that's what you're doing.
Also remember you can assign from array_of_ptrs[0] up to array_of_ptrs[num-1]. If you assign array_of_ptrs[num] you're in trouble.
Yes, what you're doing here looks correct. You are allocating an array of num pointers. So, assuming a 4 byte pointer, 4 * num bytes, all initialized to zero. If you then assign them each to another pointer, that shoudln't create a problem when you free the pointer list.
What exactly is gdb complaining about? Could it be complaining about what these pointers are pointing to going unfreed? Freeing the pointer list will not free what they each point to, if the actual structs themselves were dynamically allocated.
If you do free(array_of_ptrs); then you are in affect creating a memory leak since each entry has a pointer in that array of pointers, it would be worth your while to do a free(...); on each pointer that you have malloc'd firstly, then issue the final free(array_of_ptrs);. This is quite a similar thing when dealing with a linked list using pointers
while (!*array_of_ptrs){
struct *some_ptr_to_struct = *array_of_ptr;
free(some_ptr_to_struct);
*array_of_ptrs++;
}
free(array_of_ptrs);
Hope this helps,
Best regards,
Tom.
Assuming all of the (struct somestruct *) pointers point to memory that's already been allocated, yes, it looks correct.
As for the error, what version of gcc are you using? I tested the code on 4.3.3 and it compiles with no complaints, even with -Wall -pedantic.
Related
I have a fairly simple question on allocating memory for a struct in c and I've tried looking online, but I wasn't able to find anything. The struct is defined as:
typedef struct cblock_ {
....
} cblock, *Cblock;
When allocating memory, I've tried
Cblock new_block = malloc(sizeof(struct cblock_));
However, I keep getting getting a memory corruption error. I've tried changing the parameter of sizeof to different things, but everything is getting the same memory corruption error. What am I doing wrong?
****EDIT****
So after running valgrind, I am getting quite a bit of "invalid write of size 4" or "invalid read of size 4" throughout my code.
It's probably too much to post all of it but here's one spot where valgrinds gives me a "invalid write of size 4"
static Ablock agroup_main;
typedef struct ablock_ {
int length;
int num;
...
} ablock, *Ablock;
void init_groups() {
agroup_main = malloc(sizeof(Ablock));
agroup_main->length = DEFAULT_GROUP_LENGTH;
agroup_main->num = DEFAULT_GROUP_NUM;
}
Valgrind is saying on the line setting length that it's an invalid write of size 4, and the address is 0 bytes after a block of size 4 alloc'd. For num, it's the same except the address is 4 bytes after a block of size 4 alloc'd. I don't really understand this either, since length is just an int, and to me, the error sounds like I'm suppose to allocate memory for it...
The memory corruption is probably because of an earlier incorrect malloc (e.g. with a too small size), premature free, or genuine buffer overflow (or uninitialized pointer dereference).
Use a memory leak detector. On Linux, try valgrind
Your malloc for Cblock looks ok. The bug is probably elsewhere. Don't forget to compile with all warnings and debug info (e.g. gcc -Wall -g). Use also a debugger (e.g. gdb). You might want to disable ASLR to ease debugging (and have more reproducible runs).
You should test the result of malloc:
cblock* new_block = malloc(sizeof(struct cblock_));
if (!new_block) {
perror("malloc cblock");
exit(EXIT_FAILURE);
}
and I think you should mark clearly all the pointers in your code (so I prefer cblock* instead of Cblock which I find confusing, and which should at least be named CblockPtr).
BTW, you have been bitten by that confusion:
agroup_main = malloc(sizeof(Ablock)); // WRONG!
is incorrect, since Ablock is a pointer type (on Linux/PC, all pointers have the same size, which is 8 bytes on x86-64). You mean
agroup_main = malloc(sizeof(ablock));
if (!agroup_main)
{ perror("malloc ablock"); exit (EXIT_FAILURE); };
You really should loose the bad habit of naming pointer types in a way hiding their pointerness (and with a name similar to the pointed data).
This:
agroup_main = malloc(sizeof(Ablock));
is clearly wrong, since the type Ablock is struct ablock_ *, i.e. a pointer. You're just allocating the size of the pointer, not the size of the object being pointed at.
You should always write it like this:
agroup_main = malloc(sizeof *agroup_main);
that uses sizeof on the proper type, the type that the pointer receiving the return value points at.
I also stronly recommend against typedefing away the pointer like that, since it adds confusion. Pointers are important in C, hiding them often makes things harder to understand and follow, thus increasing the risk of error. The question "is this an object, or a pointer to an object?" is very important, and you must be able to answer it quickly and correctly, all the time.
I seem to be having some issues with malloc in my code. Here's what's going on.
I've got a struct created with a few values in it. From there, I'd like to make an array of structs. I think I've got the struct right, and some of the pointers, but I'm not sure.
Here's the struct:
typedef struct{
char name[25];
int courseID;
} course;
From there, I try to initiate the new struct and malloc it at the same time by this:
course *courses = malloc(25*sizeof(course));
From here, I'm getting the error:
Invalid conversion from 'void*' to 'course*' [-fpermissive] course
*courses = malloc(25*sizeof(course));
I don't really know what this means... I know I may be completely off course with this whole idea, so any help y'all can give would be great!
You must be using a C++ compiler. You want to compile with a C compiler.
Make sure your file name ends in .c not .cpp or .cc.
You also said you try to initialize (you said initiate but I am translating) the new struct. Malloc will not do that. Malloc allocated memory will contain random values left over from the last user of that memory. The calloc function might work better for what you want since it sets the memory to zero after allocating it.
You are initializing memory with malloc, which returns a void pointer to the allocated memory. You are then assigning this pointer to a course pointer. So there is a pointer mismatch and hence the warning. To bypass it use
course *courses = (course *)malloc(25 * sizeof(course))
Program was programmed in C and compiled with GCC.
I was trying to help a friend who was trying to use trying to (shallow) copy a value that was passed into a function. His the value was a struct that held primitives and pointers (no arrays or buffers). Unsure of how malloc works, he used it similar to how the following was done:
void some_function(int rand_params, SOME_STRUCT_TYPEDEF *ptr){
SOME_STRUCT_TYPEDEF *cpy;
cpy = malloc(sizeof(SOME_STRUCT_TYPEDEF));// this line makes a difference?!?!?
cpy = ptr;// overwrites cpy anyway, right?
//prints a value in the struct documented to be a char*,
//sorry couldn't find the documentation right now
}
I told him that the malloc shouldn't affect the program, so told him to comment it out. To my surprise, the malloc caused a different output (with some intended strings) from the implementation with the malloc commented out (prints our garbage values). The pointer that's passed into the this function is from some other library function which I don't have documentation for at the moment. The best I can assume it that the pointer was for a value that was actually a buffer (that was on the stack). But I still don't see how the malloc can cause such a difference. Could someone explain how that malloc may cause a difference?
I would say that the evident lack of understanding of pointers is responsible for ptr actually pointing to memory that has not been correctly allocated (if at all), and you are experiencing undefined behaviour. The issue is elsewhere in the program, prior to the call to some_function.
As an aside, the correct way to allocate and copy the data is this:
SOME_STRUCT_TYPEDEF *cpy = malloc(sizeof(SOME_STRUCT_TYPEDEF));
if (cpy) {
*cpy = *ptr;
// Don't forget to clean up later
free(cpy);
}
However, unless the structure is giant, it's a bit silly to do it on the heap when you can do it on the stack like this:
SOME_STRUCT_TYPEDEF cpy = *ptr;
I can't see why there difference in the print.
can you show the print code?
anyway the malloc causes memory leak. you're not supposed to allocate memory for 'cpy' because pointer assignment is not shallow-copy, you simply make 'cpy' point to same memory 'ptr' point by storing the address of the start of that memory in 'cpy' (cpy is mostly a 32/64 bit value that store address, in case of malloc, it will store the address of the memory section you allocated)
Assume the following situation:
typedef struct {
int ID1;
int ID2;
char string[256];
} Reg;
I create an array dynamically, this structure:
Reg *myReg = (Reg*) malloc(sizeof(Reg)*100); //array of type Reg with 100 positions.
And throughout this example system, I fill this array.
There comes a certain point I do not want the pointer "myReg" point to this vector. I want him to point to NULL. And also to clear the memory space occupied by malloc I did.
question:
If I do:
free(myReg);
This will make myReg will point to NULL and release the space taken up that I've allocated?
free(myReg);
This will make myReg will point to NULL and release the space taken up
that I've allocated?
It will only release the memory. Even without reading the specs, if you look at how the free function is declared, you'll see it can't actually change what the pointer is pointing to.
/* Even if it wanted, `free` can't make `ptr` point to anything else. */
void free(void *ptr);
A call to free only free's the memory allocated and returns it to the heap. It will not set the your myReg to NULL. You must do it yourself.
One way is to write a macro as below:
#define MY_FREE(ptr) free(ptr); ptr = NULL;
Other answers are correct.
To help understanding why it must be so, consider that there may be multiple pointers pointing to this memory, or to different parts of it:
Reg *myReg = (Reg*) malloc(sizeof(Reg)*100);
Reg *myReg2 = myReg;
Reg *myReg3 = &myReg[50];
When you free myReg, all these pointers are unchanged. They point to the same piece of memory as before, but this memory must no longer be used.
You, the programmer, should set them to NULL (or just avoid using them after free).
C can't find them all and set them to NULL. More modern languages, such as Java, know how to track all the pointers to a given object, but C does nothing like this.
I'm using a struct like this:
define struct _Fragment{
int a;
char *seq;
}Fragment;
I want to initialize the struct, and using the malloc() method return a dynamic memory like this
Fragment *frag=malloc(10*sizeof(Fragment));
Then I would using the frag pointer like this:
frag->seq="01001";
Then the problem occurs when I returns a lot of Fragments. the error message said that (using valgrind tool):
Uninitialised value was created by a heap allocation
who can tell me how I can deal with it. thank you!
I'm not sure you have a real problem here, but for proper etiquette, your allocation would be:
Fragment *frag=malloc(10*sizeof(Fragment));
if (frag) memset(frag,0,10*sizeof(Fragment));
The problem is that even though you use malloc to allocate memory for a Fragment structure, you haven't initialized any of the values. The memory returned by malloc is not guaranteed to be any specific value so you must explicitly initialize the struct members
Fragment* frag = malloc(10*sizeof(Fragment));
int i = 0;
for ( i = 0; i < 10; i++ ) {
frag[i].a = 0;
frag[i].seq = NULL;
}
If you want guaranteed initialized memory you should use calloc. It has an added cost of zero'ing out the memory but it may not be significant for your app.
Also you should check that malloc actually succeeds :)
The issue is malloc does not initialize any of the memory it allocates. Valgrind takes particular care to keep track of any regions of memory that have not been initialized.
You should probably take heed of the error though, the only reason Valgrind (Assuming everything works correctly) should print that error is becuase you attempted to make use of the uninitialized data somewhere, which is probably unintended. The use of unitialized variables is not in the code you have in your question, however.
Your code looks plausible, but in the following line;
Fragment *frag=malloc(10*sizeof(Fragment));
Are you sure you need 10* ?
If you need to allocate 10 Fragments, then you should take responsibility for initializing all 10.