I have a few questions about allocating memory to structs and their members.
Suppose I have a struct like this:
struct _MyStruct
{
char *a;
}
typdef struct _MyStruct MyStruct;
I want 'a' to be a dynamic string and I want to allocate memory to it. Should I allocate memory to MyStruct too in this case? Example:
MyStruct *myStr = malloc(sizeof(MyStruct)); //necessary?
MyStruct *myStrCopy = myStr;
myStrCopy->a=malloc(sizeof(char));
//checking for null//
Now suppose I allocated an X amount of memory to the struct (myStr). Now, when I allocate memory to 'a', is the memory allocated within the memory allocated to myStr, or does it get a new block of memory?
Can I allocate more memory to 'a' than I allocated to myStr?
Suppose I want to enlarge 'a' with realloc(). Should I enlarge myStr first? If I do, then by what amount of memory (sizeof(myStr)*size_of_my_string)?
I want 'a' to be a dynamic string and I want to allocate memory to it. Should I allocate memory to MyStruct too in this case?
Well, your MyStruct always needs to exist, but there are several ways to do this and you should go for the simplest one that fits your use case.
Basic approach:
MyStruct myStr;
myStr.a = malloc(N); // "N chars please!"
// You can still get a pointer to this object:
foo(&myStr);
// Don't forget to free the `char` buffer later
free(myStr.a);
Dynamic allocation — valid, but not inherently necessary:
MyStruct* myStr = malloc(sizeof(MyStruct));
myStr->a = malloc(N); // "N chars please!"
// It's already a pointer, so:
foo(myStr);
// Don't forget to free the `char` buffer later
free(myStr->a);
// And then the struct
free(myStr);
Now suppose I allocated an X amount of memory to the struct (myStr). Now, when I allocate memory to 'a', is the memory allocated within the memory allocated to myStr, or does it get a new block of memory?
It's a new block.
Each block of dynamically allocated memory is entirely separate. When you made the member variable a a pointer, you ensured that although a lives within the struct, the thing it points to does not (unless you make it point to itself, lol).
myStr (or *myStr): your malloc'd memory:
0 32 0 8 16 24 32 40 ...
+----------+ +------------------------------+
| char* a——|———————————————————————→| text or whatever here |
+----------+ +------------------------------+
(somewhere in memory) (somewhere else in memory)
The above diagram is valid no matter which way you constructed myStr.
Can I allocate more memory to 'a' than I allocated to myStr?
Yeah, whatever you want. It's separate. You have indirection.
Suppose I want to enlarge 'a' with realloc(). Should I enlarge myStr first? If I do, then by what amount of memory (sizeof(myStr)*size_of_my_string)?
No.
Just for clarification:
myStr and
a are just pointer to some memory location. This does not mean they are sharing the same memory location.
So allocating either myStr or a is not growing the variable it self.
It requests new memory somewhere in the virtual memory space of the process and stores the address in the corresponding pointer..
So to answer you question: Yes you can allocate a memory for a which is larger than myStr.
Update for better illustration:
0x000 | 0x004 | 0x008 | 0x0012 | 0x0016
^ ^
| |
myStr a
So myStr could be located in memory somewhere completly different compared to a.
Not needed to allocate for structure.Just for char* is enough. Say
MyStruct str;
str.a = malloc( sizeof(char)*10);
str will be in stack. Memory pointed by 'a' will be in heap. So when str goes out of scope, the object will be destructed. But not the dynamically allocated one which is pointed by 'a'. We have delete it manually.
The size of structure will be same won't vary with the size of dynamic memory pointed by 'a'.
Just reallocate the memory pointed by 'a'.
str.a = realloc(a, sizeof(char)*20);
First case
MyStruct *myStr = malloc(sizeof(MyStruct)); //necessary?
yes, very much. Without the allocation to myStr first, trying to dereference myStr (to reach a) is undefined behaviour.. Also, FWIW,
myStrCopy->a=malloc(sizeof(char));
allocates only memory for only one char, be sure that is what you actually want. If you really want that, in that case, you can rewrite that as
myStrCopy->a=malloc(1);
as sizeof(char) is guranteed to be 1 in C.
Every allocation through malloc() and family gives you a new memory, if successful.
You can, and you should. There is no relation actually. They are separate variables and need seperate memory allocation.
No, only realloc() on a should suffice.
Related
I am wondering where is foo and arr* being allocated in this sample program. Is foo allocated on stack with constant size or does it change when I use malloc on *arr? If I were to change foo.arr[i] for i from 0 to 4, would it change size of anything? Is foo.arr being allocated on heap? Does change of size of foo.arr change size of foo?
typedef struct {
int size;
int* arr;
} S;
int main(void) {
S foo;
int new_size = 5;
foo.size = new_size;
foo.arr = malloc(new_size * sizeof(int));
free(foo.arr);
return 0;
}
Your confusion stems from conflating the pointer with the allocated space. A pointer is, naively, just a variable that holds a value that describes the address in memory of another value. The space required for the pointer is determined by the maximum addressable space of architecture, not by the allocated block of memory. Think referentially.
In this case, foo is allocated in the stack and the size of the structure instance remains unchanged. malloc is taking care of the mechanics of memory allocation for you and returning a fresh memory address to the allocated space. Subsequently, you are taking that memory address and saving it in the arr member.
Furthermore, anything that is allocated in the stack has to be fixed size in nature. The size of the stack frame needs to be known upon calling the function. Consider the fact that every argument to a procedure has to be of known size or a pointer to some structure allocated in the heap.
Now, all that considered, there exist mechanisms to declare variable sized structures, but you would need to take care of allocating the structure in the heap and handling memory explicitly. The C99 standard introduced flexible array member, which allows placing a size undetermined array within a structure declaration, granted that it is accompanied by another member and it is placed as the last member of the structure.
When you do S foo; you allocate an element of type S in the stack composed of two int, generally 32 bits for an int, so you have allocated 64 bits.
Then you do foo.arr = malloc(new_size * sizeof(int));, you have allocated in the heap a certain amount of contiguous bits, and now foo.arr will point to (->) the first 32 bits.
Additional answers :
If I change foo.arr[i] for i from 0 to 4, would it change size of
anything?
No, since you will only change values in memory not size.
Does change of size of foo.arr change size of foo?
No, from the moment arr is allocate on heap the size of foo will remains the same.
I'm working on a C library and am trying to be very cautious about memory management. I have a function which allocates memory for a pointer, and am trying to cover the case in which the pointer is already allocated. I am wondering if I need to free the pointer before allocating over it.
char *x = (char *) malloc(12);
// ...
free(x);
x = (char *) malloc(12);
I'm unsure if the free(x) is necessary.
There is no such thing as an allocated pointer.
char *x = (char *) malloc(12); declares a pointer x. Then it allocates 12 bytes of memory and makes x point to the 12 bytes of memory.
free(x); frees the 12 bytes of memory. x still points to the 12 bytes of memory which are now freed.
x = (char *) malloc(12); allocates another 12 bytes of memory and makes x point to the new 12 bytes of memory.
If you removed free(x); then you would be allocating 2 lots of 12 bytes of memory, and not freeing the first lot. Whether that is a memory leak or not depends on how your program is supposed to work - it's only a memory leak if you aren't still using the memory for something.
Yes the free(x) is necessary. If you remove that you will definitely leak memory when you next malloc(12). Now if the sizes are really identical, then I question whether you really need that second malloc. If the sizes differ, you could use realloc() and remove the free.
It is safe, that's to say: you are not incurring in any undefined behaviour. But you are leaking memory, in case you have not saved the address given by the first malloc(), as it should be free()d at some point later.
Not doing the free() is not dangerous, but you cannot recover from that state, as you lost the reference to the memory where that chunk of memory was, so you cannot return it later (it is required by free())
If you don't control to return the memory you are given, and your program does this kind of behaviour, you can finally eat up all the memory available to your process, and this can impact your whole system.
Let's say you have a static array as an attribute of a struct
struct example {
char array [5];
};
struct example* exp = (struct example*)malloc(sizeof(struct example));
...initialize and so on...
Now is the static array in the struct considered to be on the heap or stack? In addition is it any more efficient to have an array with specified size in the struct vs a dynamically allocated array, i.e. a pointer that will point to the dynamic memory once you allocate it, attribute in terms of time to allocate? Lastily if it is on the stack does the stack eliminate the variable right when the struct is freed?
You are using the malloc function to allocate a memory.
So, using malloc function to allocate a memory for any variable, or a structure, it will allocate a memory in heap only.
You declaring a variable "a", this is the member of structure. So, in here you are not allocating a memory. You just declare a structure.
After that you allocating a memory using malloc, in here only the memory will be allocated in the heap.
In your code struct example will have size of 5 bytes which contains the character array in there. With the malloc command you have allocated 5 bytes which contains the structure completely. malloc will allocate memory off the heap. The character array array is the first (and only) 5 bytes of the allocated memory.
Given this is a small amount of memory you may just want a stack variable to hold it rather than allocate off the heap. If you are only using it for the duration of the function. In which case you can simply go:
struct example exp;
Now this is just a structure on the stack, so no overhead used in allocating it. Of course if this was a massive structure then it wouldn't be so wise to do it that way.
The array is a part of the structure. Wherever the structure is, the array is inside it.
If you use heap, it is no different from allocating a variable size array. In fact, you can increase the size of the allocation and it'll give you more space for the array. E.g. if you allocate 10 bytes, you will be able to use 10 elements in the array - array[0] to array[9]. And, in reverse, if you allocate only 2 bytes, you still can use the 2 elements of the array - array[0] and array[1]. So the number 5 that you have specified only matters for sizeof().
Of course, if you use it as a local variable in the stack, it is all different.
I think I have got my head mostly around the difference, but if I am correct, then this should be correct also:
1.)
char *string1 = (char*) malloc(runtime_determined_number);
2.)
char string2val[runtime_determined_number];
char *string2 = &string2val;
Here I would expect string1 and string2 to be the same, is this the case?
string1 and string2 are not pointed to the same memory area
string1 is a pointer pointing to a char array allocated dynamically with malloc
string2 is a pointer pointing to a char array allocated statically
They both point to uninitialized blocks of memory of the same length. So in that respect they are the same, yes.
Note that in case 1, you are responsible for freeing the memory once you're finished. And in case 2, you can't safely return the pointer from a function as the memory will go out of scope on exit.
Using malloc you are asking the OS for memory during runtime. If malloc succeeded you are able to work with the allocated memory. You must deallocate this memory later on!
In your second part you are creating a char-array and then assign its address to a pointer. In this case the memory is taken from the stack and will be freed automatically when the array goes out of scope.
Your char*s won't be the same as they will be pointing to different locations in memory. There is aminor chance they contain the same garbage as you have not initialized them...
They are similar in that they have the same type and have at least runtime_determined_number bytes allocated for them.
They are different in that:
the first version requires an explicit free() to avoid a memory leak;
the lifetime of the two objects may or may not be the same.
Note that the second version is only valid in C99, since it makes use of a variable-length array.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C Array Instantiation - Stack or Heap Allocation?
When dynamically allocating a struct containing a char pointer, what happens with the actual char pointer? Where is it stored?
And once the struct is freed, is the char pointer freed along with it?
For example consider the following struct:
struct mix
{
int a;
float b;
char *s;
};
typedef struct mix mix;
And then the following code that allocates memory for it:
int main()
{
mix *ptr = (mix*)malloc(sizeof(mix));
ptr->a = 3;
ptr->b = 4.5f;
ptr->s = "Hi, there, I'm just a really long string.";
free(ptr);
return 0;
}
Is *s allocated on the stack and then freed along with *ptr? I can imagine it is indeed allocated on the stack as it's not in any way dynamically allocated (unless malloc has some functionality I'm not aware of). And I guess 'going out of scope' for *s would be at the point of freeing *ptr. Or have I got it completely wrong? :)
Thanks very much!
The space for the char* member named s is allocated on the heap, along with the rest of the members of mix after the call to malloc() (whose return value you do not need to cast). The string literal to which s is assigned is not allocated on the heap or the stack, but is part of the actual binary and has static storage duration. So this:
ptr->s = "Hi, there, I'm just a really long string.";
assigns the address of the string literal to ptr->s. If you want ptr->s to point to something other than a string literal then you need to malloc() memory for it. And for every malloc() there must be a free() so ptr->s would need to be free()d before ptr is (if ptr->s is pointing to dynamically allocate memory only).
After the call to free(), dereferencing ptr is undefined behaviour.
When you dynamically allocate mix with malloc(), you are actually allocating a block of memory to store mix structure data members, i.e.
an int (a)
a float (b)
a pointer to a char (s)
And when you call free(), you just release that block.
So, you don't allocate the string, you just allocate the string pointer.
If you want to dynamically allocate the string, you must do it explicitly (with another call to malloc()), and to avoid memory leaks you should also free the string explicitly, using free().
When you malloc for ptr, memory is allocated for all members of the struct including the pointer s which is no different to memory allocated for any other member of the struct.
You are assigning a string literal to s, so it's fine which is usually stored in the read-only section. Otherwise, you'll need to malloc for the ptr->s as well and free. Since, it's a string literal, there's no need to free s here (doing so is UB).
mix* ptr is allocated on the stack. The contents that ptr point at, a variable of type mix, is allocated dynamically on the heap, including the pointer s.
Please note that s doesn't point at anything, the pointer doesn't do anything useful. You have to set it to point at something, which could be allocated anywhere. Whatever it points to is not freed when your struct is freed. In this case you set it to point at a constant string literal allocated in ROM, so you won't need to worry about that.
Is *s allocated on the stack
*s (that is, the result of dereferencing the pointer s) isn't allocated at all. Following the malloc, ptr->s is an uninitialized pointer. It doesn't point to anything, and the expression *(ptr->s) has undefined behavior until you do ptr->s = "Hi, etc".
Once you've initialized ptr->s to point to the string literal, *(ptr->s) is the first character of the string literal, so it probably exists in some data section of the executable. Nothing is dynamically allocated other than the sizeof(mix) bytes for the struct (probably 12 bytes on a 32bit implementation).
what happens with the actual char pointer? Where is it stored?
char* is also like other members, take some bytes(take 8 byte in 64 bit machine, similar to other pointer). In your case, you are allocating memory for that structure instance in heap. so the memory for this pointer also will be allocated in same heap block which is allocated for that structure instance.
Consider this code. This gives where the char* will be:
#include <stdio.h>
typedef struct
{
int a;
float b;
char *s;
}mix;
int main()
{
printf("\n%d ,float:%d, int:%d, char*:%d", sizeof(mix), sizeof(float), sizeof(int), sizeof(char*));
return 0;
}
so size of this structure is 16 bytes. consist of 4 byte integer, 4 byte float and 8 byte char*. (In 64 bit OS, char* will be 4 bytes if OS is 32 bit.)
And once the struct is freed, is the char pointer freed along with it?
Usually the block which is pointed by char* will not be freed(If it points to a block allocated by malloc()). only the structure block will be freed. we know free() needs valid address which is returned during allocation for peaceful de-allocation. If you free without freeing that char*, it will leads to memory leak.
But your case "Hi, there, I'm just a really long string.";
the above given string is string literal which is allocated in read-only section of your program.
use gcc -S Yourprogram.c
This will generate .s file. You can look at .read_only section for this string. so even you delete your structure instance, there will be no memory leak. Because you are just pointing a address which is read-only. You are not at-all allocating memory for this string.