I've got a theoretical question on allocating memory for structs. Consider the following code IN THE MAIN FUNCTION:
I have the following struct:
typedef struct {
char *descr = NULL;
DWORD id = 0x00FFFF00;
int start_byte = 0;
int end_byte = 0;
double conversion_factor = 0.0;
} CAN_ID_ENTRY;
I want an array of this structs, so I'm allocating a pointer to the first struct:
can_id_list = (CAN_ID_ENTRY **)malloc(sizeof(CAN_ID_ENTRY));
And then I'm allocating memory for the first struct can_id_list[0]:
can_id_list[0] = (CAN_ID_ENTRY *)malloc(sizeof(CAN_ID_ENTRY));
Now the problem is, that I don't know HOW MANY of these structs I need (because I'm reading a CSV-File and I don't know the amount of lines/entries). So I need to enlarge the struct-pointer can_id_list for a second one:
can_id_list = (CAN_ID_ENTRY **)malloc(sizeof(CAN_ID_ENTRY));
And then I'm allocating the second struct can_id_list[1]:
can_id_list[1] = (CAN_ID_ENTRY *)malloc(sizeof(CAN_ID_ENTRY));
can_id_list[1]->id = 6;
Obviously, this works. But why? My point is the following: Normally, malloc allocates memory in one block in the memory (without gaps). But if another malloc is done BEFORE I'm allocating memory for the next struct, there is a gap between the first and the second struct. So, why can I access the second struct via can_id_list[1]? Does the index [1] store the actual address of the struct, or does it just calculate the size of the struct and jumps to this address beginning on the offset of the struct-pointer can_id_list (-> can_id_list+<2*sizeof(CAN_ID_ENTRY))?
Well, my real problem is, that I need to do this inside a function and therefore I need to pass the pointer of the struct to the function. But I don't know how to do this, because can_id_list is already a pointer ... and the changes must also be visible in the main method (that's the reason i need to use pointers).
The mentioned function is this one:
int load_can_id_list(char *filename, CAN_ID_ENTRY **can_id_list);
But is the parameter CAN_ID_ENTRY **can_id_list correct? And how do i pass the struct-array into this function? And how can i modify it inside??
Any help would be great!
EDIT: Casting malloc returns - Visual Studio forces me to do that! (Because it's a C++ project i think)
As the comments already said, the source of your confusion is can_id_list = (CAN_ID_ENTRY **)malloc(sizeof(CAN_ID_ENTRY)); allocating the wrong amount of memory. It probably gave you space for a few pointers to be stored, not just one. Should be can_id_list = (CAN_ID_ENTRY **)malloc(sizeof(CAN_ID_ENTRY*));.
To answer the question at the end,
But is the parameter CAN_ID_ENTRY **can_id_list correct? And how do i
pass the struct-array into this function? And how can i modify it
inside??
If you want to enlarge the size of the array within another function, you need to pass CAN_ID_ENTRY*** pr so you can set *ptr = realloc(...) inside as needed. Realloc may give you the new chunk of memory at a different address, so you can't simply pass in a CAN_ID_ENTRY** ptr then do realloc(ptr). See https://www.tutorialspoint.com/c_standard_library/c_function_realloc.htm
Related
Hi i'm relatively new to c and was wondering if anyone could explain what exactly i'm doing with the following code.
I have a struct:
typedef struct free_list_header {
u_int32_t magic; // ought to contain MAGIC_FREE
vsize_t size; // # bytes in this block (including header)
vlink_t next; // memory[] index of next free block
vlink_t prev; // memory[] index of previous free block
} free_header_t;
and I'm initialising it within a function using the following...
void vlad_init(u_int32_t size)
{
int sizePow2 = pow(2, ceil(log(size)/log(2)));
memory = malloc(sizePow2*sizeof(char));
memory_size = sizePow2;
strategy = BEST_FIT;
free_header_t *freeHeader = (free_header_t*)memory;
freeHeader->magic = MAGIC_FREE; // the unique value
freeHeader->size = memory_size; // amount we malloc'd
freeHeader->next = 0; // position of next free block
freeHeader->prev = 0; // position of prev free block
free_list_ptr = 0;
}
my question is what exactly am i doing here and why is it necessary?
free_header_t *freeHeader = (free_header_t*)memory;
So... i'm declaring a new struct by pointing to it named "freeHeader"? and that is a pointer to it in the memory i have allocated? So this is a way of putting the struct into the malloc'd area to access it out of the function in which im initializing it?
Malloc returns a void pointer (type void*). This means it returns a pointer to a memory address and that pointer is not pointing to any specific type. So after the line:
memory = malloc(sizePow2*sizeof(char)); //sizePow2 is n bytes to allocate
memory is a pointer of type (void *).
free_header_t *freeHeader = (free_header_t*)memory;
On the left hand side here you are creating a pointer named freeHeader that points to a memory address containing something of type free_header_t
Since you explicitly said this pointer is pointing to an address of type free_header_t to you are casting the other side (currently of type void *) to match it as free_header_t *.
NOTE in C, this works but is not necessary. The compiler will automatically cast a void * to whatever type you need. However writing code like this is good practice, in C++ you need to explicitly do this.
free_header_t * freeHeader = (free_header_t*)memory;
you declared a pointer (not an actual struct) to free_header_t struct named freeHeader and you assigned it the value of the pointer named memory. since memory is a pointer to char and yours is a pointer to something else, you used casting.
You currently have only a pointer to an allocated area (of size sizePow2*sizeof(char) - note that the size of the struct should be less or equal to the size of the allocated memory).
Your code is essentially equivalent to:
free_header_t *freeHeader = malloc(sizePow2 * sizeof(char));
It's allocating a block of memory that contains sizePow2 bytes, and then using that as the address of a free_list_header structure.
The reason it uses the memory variable is because some other code is going to use the next and prev members as indexes into that block of memory. As the name implies, this structure just contains the data at the beginning of the memory block, the rest of the memory is managed with other structures.
memory = malloc(sizePow2*sizeof(char));
You are allocating some memory here. It would be good to just use
memory = malloc(sizeof(struct free_list_header));
to store an object of the structure.
free_header_t *freeHeader = (free_header_t*)memory;
Here you are declaring a pointer which would point to memory allocated earlier. You did not technically declare an object of the structure. And you are not putting the structure in to malloc-ed area, you are instead treating the malloc-ed area as an object of the structure.
free_header_t freeHeader = {0}; would be declaring an object of the structure.
Every time you call malloc() function, the operating system returns you a single memory address. When you cast this pointer to a specific type you tell to compiler that every element stored in the memory allocated will consume the size of the specified type and this get the things easier.
Let suppose that you declare a uint64_t* and the size of allocation it's 100 times the size of uint64_t, so you're asking for 800 bytes for the operating system, once the uint64_t takes 8 bytes. If you do not cast this pointer, every time you increase the address with your_variable++ your program will skip only one byte and you will get in the "middle of the number and will get a weird value", but if you cast your pointer to a uint64_t and increase the address with your_variable++ your program will skip 8 bytes, going directly to the next number.
In your example, you're telling to the operating system that your pointer will store types of free_header_t. You're not obligated to do it, but it is a very good practice.
And yes, if you return this address to another function, the other function can change the value stored in this memory area easily.
Hope it helps!
I have a function that will add a new position to an array by reallocating new memory every time it is called.
The problem is that, for each call I need it to add one position to the array, starting from 1 at first call, but I understand that I have to mallocate before reallocating.
So my question is, can I initially do something like p = malloc(0) and then reallocate for example using p = (int *)realloc(p,sizeof(int)) inside my function? p is declared as int *p.
Maybe with a different syntax?
Of course I could make a condition in my function that would mallocate if memory hasn't been allocated before and reallocate if it has, but I am looking for a better way.
And the second problem I have is... Once reallocated more positions, I want to know the size of the array.
I know that if, for example, I declare an array a[10], the number of elements would be defined by sizeof(a)/sizeof(a[0]), but for some reason that doesn't work with arrays declared as pointers and then reallocated.
Any advice?
You could initialize your pointer to NULL, so that the first time you call realloc(yourPointer, yourSize), it will return the same value as malloc(yourSize).
For your second problem, you could use a struct that contains your pointer and a count member.
struct MyIntVector {
int * ptr;
size_t count;
}
Then you probably will want to define wrapper functions for malloc, realloc, and free (where you could reset ptr to NULL), that takes your struct as one of the parameters, and updates the struct as needed.
If you want to optimize this for pushing 1 element at a time, you could add a allocatedCount member, and only realloc if count == allocatedCount, with a new allocatedCount equals (for example) twice the old allocatedCount.
You should implement this in a MyIntVector_Push(MyIntVector *, int ) function.
You will then have a simplified c version of c++ std::vector<int> (but without automatic deallocation when the object goes out of scope).
As ThreeStarProgrammer57 said just use realloc.
realloc(NULL, nr_of_bytes) is equivalent to malloc(nr_of_bytes)
so
p = realloc(p, your_new_size)
will work just fine the first time if p is initialized to NULL. But be sure to pass the number of bytes you need after resizing, not the additional space that you want, as you have written your question.
As regarding the size, you have to keep track of it. That's the way C was designed.
I'm trying to make a program that basically picks a specific piece of source code and adds some other specific code into it. The program is just to big to put it all inside my question, but basically I have this "actors" struct:
typedef struct actors_s {
int num;
char *src_path;
char *project_path;
int *papify;
char *actor_path[];
} actors_s;
As you can see these are almost all pointers and the last one is an array of strings. This needs to be done this way because the number of "actor elements" depends on the input every time.
The problem:In an specific test case, I have a case with 'num' members in the actor_path array. Then I first call malloc only once this way:
*actors->actor_path = malloc(actors->num);
My logic tells me I shouldn't be using the '*' operator here but without it I get an error, this is possibly where the problem is. So, a function is called that allocates a new memory space for every new member (never going further of 'num' members):
int size = strlen(name)+strlen(actors->project_path)+strlen("/src/")+strlen(".c")+4;
actors->actor_path[i] = malloc(size);
(The malloc calls are properly tested if successful in the actual program)
This is called inside a function that is called for every "actor_path" element. In this test example I have three actors.
Mysteriously enough, on the third call of this malloc, the src_path element of the struct, which was properly allocated and set to a string once in the beginning of the program (and never touched again) is freed (I think so, at least it is changed into random numbers and symbols if I watch it in debug mode).
Anyone has any idea how and why is this possible? How do I fix this?
Thanks in advance.
EDIT:
Here are some screenshots from the debug watch window: http://imgur.com/a/aB1uv
First call to malloc: all OK.
Second call to malloc: all OK.
Third call to malloc: src_path gets erased!!
[] in latest array element is called flexible array member. It means structure have an array that starts just after structure itself, and its size is unspecified. You have to allocate memory for this manually. E.g.
actors_s *actor = malloc(sizeof(*actor) + sizeof(char*) * num);
Then just assign at most num elements into actor_path (each element is pointer to char).
about *actors->actor_path = malloc(actors->num);
actors->actor_path is an array of pointers, so *actors->actor_path is the first pointer in actors->actor_path, i.e. actors->actor_path[0].
When doing this, you actually allocate actors->num bytes memory for actors->actor_path[0].
Now, accessing actors->actor_path[0] is OK, while accessing actors->actor_path[1], actors->actor_path[2], actors->actor_path[3],... may cause problems, say, rewrite src_path...
about the solution
#keltar is right. In this way, the resource for actors->actor_path[0], actors->actor_path[1], actors->actor_path[2], ..., actors->actor_path[num - 1] is correctly allocated.
I have this structure
typedef struct Rectangle{
char *name;
int size;
}RCG;
typedef struct Shapes{
RCG *rectangle;
}SHP;
Here is the problem of mine I dynamically allocated the RCG with 20 ;
SHP shp;
shp.rectangle = (RCG*)malloc(sizeof(RCG *) * 20)
also allocated memory to the name of rectangle inside the pointer;
shp.rectangle[0].name = malloc(10*sizeof(char));
shp.rectangle[0].name = "big";
how can I free the name??
what i did is
free(shp.rectangle[0].name);
it gives me an error of "the heap may be corrupted"
I use visual studio 2010
When you use the following line
shp.rectangle[0].name = "big";
You are setting the pointer to a different location than the original return value of malloc.
What you probably want instead is the following.
memcpy(shp.rectangle[0].name, "big", strlen("big") + 1)
Also, whether the pointer is inside a structure is not relevant. You would have the same issue even if the pointer was not defined inside a structure.
Update: As mentioned in the comment below, since we dealing with strings in this particular case, it is probably more appropriate to use the function strncpy instead of the more general memcpy.
strncpy(shp.rectangle[0].name, "big", 10*sizeof(char))
Note that 10*sizeof(char) is hardcoded above because that is the size of the earlier malloc.
This: shp.rectangle[0].name = "big"; does not copy the chars into the allocated space but assigns the address of the string "big" to the pointer name. The allocated memory is not referenced any longer anywhere so you lost any way of freeing it. Instead you try to free the string "big" which is part of your executable, actually.
memcpy or even better strcpy is commonly used for copying strings; those will assign to each char in name the corresponding value in "big".
I'm doing a project where our professor has given us code with variables and prototype declarations that we are unable to change. One is a struct, with a pointer to that struct is typedef'd as pStudentRecord:
typedef struct
{
char* firstName;
char* lastName;
int id;
float mark;
}* pStudentRecord;
With a pointer to this type called g_ppRecords. This will be a dynamic array of pointers to the structs above.
Here's where my question comes in. The records will be read from a file. If the filename specified doesn't exist then it creates a new one. I'm initializing the g_ppRecords pointer whenever the user adds the first new record:
if(!n) //where n = number of records
g_ppRecords = (pStudentRecord*) malloc(sizeof(pStudentRecord));
g_ppRecords[n] = (pStudentRecord) malloc(16);
This code works every time I've ran it so far, but I'm not sure how. If I add more records then a new pointer (pStudentRecord) will be created in the next position in g_ppRecords. By my understanding, I haven't allocated the space for that new pointer, yet every time it works without even a hint of a problem. I can access the members of the new structs fine and I'm not getting a heap corruption error or access violation or anything like that. Are my concerns correct or am I doubting myself?
Based on the code that you've shown, your concerns are valid.
This line:
g_ppRecords = (pStudentRecord*) malloc(sizeof(pStudentRecord));
Allocates only enough space for a single pStudentRecord. Think of this as an array of pStudentRecord with only a single element, at g_ppRecords[0].
If I add more records then a new pointer (pStudentRecord) will be created in the next position in g_ppRecords.
Now the problem is what might happen when you do what you've described here. What happens when you add a new pointer? Unless you use realloc to get more space for g_ppRecords, you don't have room in that array for more pointers to records. If you malloc a new pointer at the second element, i.e.:
g_ppRecords[1] = (pStudentRecord) malloc(16);
Then you're using memory, g_ppRecords[1], that you haven't allocated. This may appear to work, but this memory doesn't belong to you. Keep adding new pointers and eventually your program will break. Or your program may break because of something totally unrelated in another part of your code.
The fix is that you should initially allocate your array so that it can hold multiple pointers, instead of only one. How can you do this with your first malloc line?
I should add that when you allocate memory for a struct using malloc(16) you're making assumptions about the data structure that you shouldn't make, specifically that the struct will always occupy 16 bytes. Given your typedef: straight to a pointer from an anonymous struct, you can change that 16 to something more general, but this isn't directly related to your question, and is something that you should ask your professor about.
As a general rule, try to avoid malloc( sizeof( type )), especially when the type is obfuscated by a typecast. It is much safer to call sizeof on a variable: malloc( sizeof x ). Also, in C, you should not cast the return from malloc. In other words, instead of allocating space for only one record with:
g_ppRecords = (pStudentRecord*) malloc(sizeof(pStudentRecord));
it would be better to allocate space for n records by writing:
g_ppRecords = malloc( n * sizeof *g_ppRecords );
typedef struct
{
char* firstName;
char* lastName;
int id;
float mark;
}* pStudentRecord;
This is an anonymous struct. A bit weird here, but maybe to teach you something. Do this to create a new one:
pStudentRecord ptr;
ptr = malloc(sizeof(*ptr));
This will automatically malloc the right amount of memory.
You've still got problems because you need to malloc the array to hold the pointers. For that do this:
pStudentRecord* g_ppRecords = malloc(n * sizeof(pStudentRecord));
You can then use g_ppRecords like this:
pStudentRecord ptr = g_ppRecords[3];
Putting it all together we have our custom allocator:
pStudentRecord* g_ppRecords = malloc(n * sizeof(pStudentRecord));
for (size_t i = 0; i < n; ++i)
{
pStudentRecord ptr;
g_ppRecords[i] = malloc(sizeof(*ptr));
}
I wrote all this without compiling and testing, so there may be errors (but its not my homework :-) )