C - How to free a struct array cell completely - c

I read some other questions like this here on stack overflow, and I fixed the problem I had with my use of free();
I have a struct array of this type:
typedef struct _event {
char* desc;
int start;
int end;
} event;
But it seems I can only free the desc, while if I try to use the free for the two integers (start/end), it doesn't work.
Reading the other answers in other posts, I understood that I can't free something I haven't malloc'd. The point is: I don't need to malloc() an integer. But on my exercise, I really need to erase that array block. (I don't mean the whole array, just that block).
I don't want to put much code in this post to don't bother the reader, but if you need please tell me!
At the moment I am using:
free(event[i].desc);
in a for loop under a certain if statement.
The question is how to free also event[i].start and event[i].end ?
Thank you in advance, I am sorry about the dumb question, but I wanted to know if it is possible to free the entire cell instead of using a marker like '0'.
P.S. If you know a good article or tutorial about free() function, can you please link it to me?

If you allocated event as a block, e.g.
event * p = (event *) malloc(sizeof(event);
p->desc = (char *) malloc (sizeof(char) * SIZE); // presume SIZE defined earlier
then, you could free in reverse sequence as below:
free(p->desc);
free(p); // will deallocate the entire block
Hope this is what you meant to know.

It is important to understand that you cannot free just a part of your structure:
In your case you have a pointer on char and 2 int.
The char* can store an address you get via malloc: this can be freed. But the 2 int cannot.
If for some reason they became irrelevant and you really need to get rid of these variables, then you probably defined your structure the wrong way: you might want to split it.
An other solution could be to reset these fields with a default value (like 0 or -1 or whatever you define), and free the  char * as #Debasish Jana explained.

Related

c code: error in the syntax of structs and their fields

So i wrote the following code.
NameOfStruct *S;
if (statement) {
S = (S)->property[10];
}
I defined the structure beforehand. So the error i am getting is this:
'*S' is a pointer; did you mean to use '->'? and then the line where i typed the code. I find this weird since they ask me if i meant -> while that is exactly what i use. If i instead use the following code
S = (*S)->property[10]
then i get that that there is a wrong assignment with an incompatible pointer type.
What is happening here?
Your question is kind of hard to understand, but I think I understood enough to help you.
I think your problem might be in the way you defined the struct, and not on the code that uses it.
Firstly, I don't know what NameOfStructis, so i'll define one in this example:
typedef struct test {
int someValue;
char someString[10];
}EXAMPLE;
What this does is define a struct. You can either call for struct test or EXAMPLE when you want to do something with that struct.
Now, when it comes to use that struct, you can only use -> when you are dealing with pointers. Also, when using Structs, you should allocate memory using malloc().
In your main, you should have something like this:
int main () {
//Declare pointer to struct and allocate memory.
EXAMPLE *test = (EXAMPLE*) malloc(sizeof(EXAMPLE));
//Manipulate data on struct
test->someValue = 10;
test->someString = "Testing";
free(test);
}
This way, you should be left with a struct where on someValue the content is 10and on someString the content is Testing
Also, if in your main you don't feel like using EXAMPLE you can also just use struct test. Don't forget to free the memory you allocated when you don't need it anymore.
PS: Please, next time you ask a question be sure to give a good explanation on what the problem is, show us what your attempt was, and give us the input/output you were expecting paired with the input/output that you got. If you're left with any questions, feel free to reply to this answer and I'll try to help you

Freeing the memory arrays of structures in C

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.

C Memory Overflow (v2)

EDIT: Updated code with new Pastebin link but it's still stopping at the info->citizens[x]->name while loop. Added realloc to loops and tidied up the code. Any more comments would be greatly appreciated
I'm having a few problems with memory allocation overflowing
http://pastebin.com/vukRGkq9 (v2)
No matter what I try, simply not enough memory is being allocated for info->citizens and gdb is often saying that it cannot access info->citizens[x]->name.
On occasion, I'll even get KERN_INVALID_ADDRESS errors directly after printf statements for strlen (Strlen is not used in the code at the point where gdb halts due to the error, but I'm assuming printf uses strlen in some way). I think it's something to do with how the structure is being allocated memory. So I was wondering if anyone could take a look?
You shouldn't do malloc(sizeof(PEOPLE*)), because it allocates exactly amount of bytes for pointer (4 bytes on 32bit arch).
Seems the thing you want to do is malloc(sizeof(PEOPLE) * N) where N is the max. number of PEOPLE you want to put into that memory chunk.
Clearly the problem lies with:
info->citizens = malloc(sizeof(PEOPLE *));
info->citizens[0] = malloc(sizeof(PEOPLE *));
info->citizens[1] = malloc(sizeof(PEOPLE *));
Think about it logically what you are trying to do here.
Your structs should almost certainly not contains members such as:
time_t *modtimes;
mode_t *modes;
bool *exists;
Instead you should simply use:
time_t modtimes;
mode_t modes;
bool exists;
In that way you do not need to dynamically allocate them, or subsequently release them. The reasons are that a) they're small and b) their size is known in advance. You would use:
char *name;
for a string field because it's not small and you don't know in advance how large it is.
Elsewhere in the code, you have the folllowing:
if(top)
{
PEOPLE *info;
info = malloc(sizeof(PEOPLE *));
}
If top is true then this code allocates a pointer and then immediately leaks it -- the scope of the second info is limited to the if statement so you can neither use it later nor can you release it later. You would need to do something like this:
PEOPLE *process(PEOPLE *info, ...)
{
if (top)
{
info = malloc(sizeof(PEOPLE));
}
info->name = strdup("Henry James");
info->exists = true;
return info;
}
It seems you have one too many levels of indirection. Why are you using **citizens instead of *?
Also, apart from the fact that you are allocating the space for a pointer, not the struct, there are a couple of weird things, such as the local variable info on line 31 means the initial allocation is out of scope once the block closes at line 34.
You need to think more clearly about what data is where.
Lots of memory allocation issues with this code. Those mentioned above plus numerous others, for example:
info->citizens[masterX]->name = malloc(sizeof(char)*strlen(dp->d_name)+1);
info->citizens[masterX]->name = dp->d_name;
You cannot copy strings in C through assignment (using =). You can write this as:
info->citizens[masterX]->name = malloc(strlen(dp->d_name)+1);
strcpy(info->citizens[masterX]->name, dp->d_name);
Or you could condense the whole allocate & copy as follows:
info->citizens[masterX]->name = strdup(dp->d_name);
Similarly at lines 143/147 (except in that case you have also allocated one byte too few in your malloc call).

Resizing a char[x] to char[y] at runtime

OK, I hope I explain this one correctly.
I have a struct:
typedef struct _MyData
{
char Data[256];
int Index;
} MyData;
Now, I run into a problem. Most of the time MyData.Data is OK with 256, but in some cases I need to expand the amount of chars it can hold to different sizes.
I can't use a pointer.
Is there any way to resize Data at run time? How?
Code is appreciated.
EDIT 1:
While I am very thankful for all the comments, the "maybe try this..." or "do that", or "what you are dong is wrong..." comments are not helping. Code is the help here. Please, if you know the answer post the code.
Please note that:
I cannot use pointers. Please don't try to figure out why, I just can't.
The struct is being injected into another program's memory that's why no pointers can be used.
Sorry for being a bit rough here but I asked the question here because I already tried all the different approaches that thought might work.
Again, I am looking for code. At this point I am not interested in "might work..." or " have you considered this..."
Thank you and my apologies again.
EDIT 2
Why was this set as answered?
You can use a flexible array member
typedef struct _MyData
{
int Index;
char Data[];
} MyData;
So that you can then allocate the right amount of space
MyData *d = malloc(sizeof *d + sizeof(char[100]));
d->Data[0..99] = ...;
Later, you can free, and allocate another chunk of memory and make a pointer to MyData point to it, at which time you will have more / less elements in the flexible array member (realloc). Note that you will have to save the length somewhere, too.
In Pre-C99 times, there isn't a flexible array member: char Data[] is simply regarded as an array with incomplete type, and the compiler would moan about that. Here i recommend you two possible ways out there
Using a pointer: char *Data and make it point to the allocated memory. This won't be as convenient as using the embedded array, because you will possibly need to have two allocations: One for the struct, and one for the memory pointed to by the pointer. You can also have the struct allocated on the stack instead, if the situation in your program allows this.
Using a char Data[1] instead, but treat it as if it were bigger, so that it overlays the whole allocated object. This is formally undefined behavior, but is a common technique, so it's probably safe to use with your compiler.
The problem here is your statement "I can't use a pointer". You will have to, and it will make everything much easier. Hey, realloc even copies your existing data, what do you want more?
So why do you think you can't use a pointer? Better try to fix that.
You would re-arrange the structure like that
typedef struct _MyData
{
int Index;
char Data[256];
} MyData;
And allocate instances with malloc/realloc like that:
my_data = (MyData*) malloc ( sizeof(MyData) + extra_space_needed );
This is an ugly approach and I would not recommend it (I would use pointers), but is an answer to your question how to do it without a pointer.
A limitation is that it allows for only one variable size member per struct, and has to be at the end.
Let me sum up two important points I see in this thread:
The structure is used to interact between two programs through some IPC mechanism
The destination program cannot be changed
You cannot therefore change that structure in any way, because the destination program is stuck trying to read it as currently defined. I'm afraid you are stuck.
You can try to find ways to get the equivalent behavior, or find some evil hack to force the destination program to read a new structure (e.g., modifying the binary offsets in the executable). That's all pretty application specific so I can't give much better guidance than that.
You might consider writing a third program to act as an interface between the two. It can take the "long" messages and do something with them, and pass the "short" messages onward to the old program. You can inject that in between the IPC mechanisms fairly easily.
You may be able to do this like this, without allocating a pointer for the array:
typedef struct _MyData
{
int Index;
char Data[1];
} MyData;
Later, you allocate like this:
int bcount = 256;
MyData *foo;
foo = (MyData *)malloc(sizeof(*foo) + bcount);
realloc:
int newbcount = 512;
MyData *resized_foo;
resized_foo = realloc((void *)foo, sizeof(*foo) + newbcount);
It looks like from what you're saying that you definitely have to keep MyData as a static block of data. In which case I think the only option open to you is to somehow (optionally) chain these data structures together in a way that can be re-assembled be the other process.
You'd need and additional member in MyData, eg.
typedef struct _MyData
{
int Sequence;
char Data[256];
int Index;
} MyData;
Where Sequence identifies the descending sequence in which to re-assemble the data (a sequence number of zero would indicate the final data buffer).
The problem is in the way you're putting the question. Don't think about C semantics: instead, think like a hacker. Explain exactly how you are currently getting your data into the other process at the right time, and also how the other program knows where the data begins and ends. Is the other program expecting a null-terminated string? If you declare your struct with a char[300] does the other program crash?
You see, when you say "passing data" to the other program, you might be [a] tricking the other process into copying what you put in front of it, [b] tricking the other program into letting you overwrite its normally 'private' memory, or [c] some other approach. No matter which is the case, if the other program can take your larger data, there is a way to get it to them.
I find KIV's trick quite usable. Though, I would suggest investigating the pointer issue first.
If you look at the malloc implementations
(check this IBM article, Listing 5: Pseudo-code for the main allocator),
When you allocate, the memory manager allocates a control header and
then free space following it based on your requested size.
This is very much like saying,
typedef struct _MyData
{
int size;
char Data[1]; // we are going to break the array-bound up-to size length
} MyData;
Now, your problem is,
How do you pass such a (mis-sized?) structure to this other process?
That brings us the the question,
How does the other process figure out the size of this data?
I would expect a length field as part of the communication.
If you have all that, whats wrong with passing a pointer to the other process?
Will the other process identify the difference between a pointer to a
structure and that to a allocated memory?
You cant reacolate manualy.
You can do some tricks wich i was uning when i was working aon simple data holding sistem. (very simple filesystem).
typedef struct
{
int index ;
char x[250];
} data_ztorage_250_char;
typedef struct
{
int index;
char x[1000];
} data_ztorage_1000_char;
int main(void)
{
char just_raw_data[sizeof(data_ztorage_1000_char)];
data_ztorage_1000_char* big_struct;
data_ztorage_250_char* small_struct;
big_struct = (data_ztorage_1000_char*)big_struct; //now you have bigg struct
// notice that upper line is same as writing
// big_struct = (data_ztorage_1000_char*)(&just_raw_data[0]);
small_struct = (data_ztorage_250_char*)just_raw_data;//now you have small struct
//both structs starts at same locations and they share same memory
//addresing data is
small_struct -> index = 250;
}
You don't state what the Index value is for.
As I understand it you are passing data to another program using the structure shown.
Is there a reason why you can't break your data to send into chunks of 256bytes and then set the index value accordingly? e.g.
Data is 512 bytes so you send one struct with the first 256 bytes and index=0, then another with the next 256 bytes in your array and Index=1.
How about a really, really simple solution? Could you do:
typedef struct _MyData
{
char Data[1024];
int Index;
} MyData;
I have a feeling I know your response will be "No, because the other program I don't have control over expects 256 bytes"... And if that is indeed your answer to my answer, then my answer becomes: this is impossible.

Struct initialization problem?

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.

Resources