malloc an array of struct pointers, need help please - c

I am trying to use malloc to allocate heap memory for an array of struct pointers, but I cannot get it to work. Below is my code, but when I compile with gcc, I got errors like this "error: invalid type argument of ‘->’ "
The array I want to set up an array of mystruct_pointer, which should point to the actual __mystruct_t, and I think I can use "->" on its member field. Where is wrong with my code? I think it should work. thanks
typedef struct
{
int id;
bool status;
} __mystruct_t;
typedef __mystruct_t* mystruct_pointer;
mystruct_pointer struct_ptr_array;
void my_init(int number)
{
struct_ptr_array = (mystruct_pointer) malloc(sizeof(__mystruct_t) * number);
int i;
for (i = 0; i < number; i++) /* initialize the array of struct pointers */
{
struct_ptr_array[i]->id = i;
struct_ptr_array[i]->status = false;
}
}

Replace '->' by '.'. Since 'struct_ptr_array[i]' already dereference the pointer.

Problems like these come from doing obscure things. You typedef-hide a pointer and instantly you have made the program unreadable to yourself. And that's the only thing the typedef achieved. So never hide pointers with typedefs, it is very bad practice.
Other issues:
Avoid double underscore because that's reserved for compiler identifiers.
Don't cast the result of malloc, because doing so is completely pointless in C and also potentially dangerous on old C compilers.
Handle the case where malloc fails because there's no heap space available.
Never use variables with global scope, it is very bad practice that leads to spaghetti code. And there is never a reason to do so in C.
The code should be fixed as follows:
typedef struct
{
int id;
bool status;
} mystruct_t;
static mystruct_t* struct_ptr_array;
void my_init(int number)
{
struct_ptr_array = malloc(sizeof(mystruct_t) * number);
if(struct_ptr_array == NULL)
{
handle_error();
return ;
}
for (int i = 0; i < number; i++) /* initialize the array of struct pointers */
{
struct_ptr_array[i].id = i;
struct_ptr_array[i].status = false;
}
}

struct_ptr_array is a pointer, but you index it, so you get an actual __mystruct_t, not the pointer. Thus, simply use:
struct_ptr_array[i].id = i;
struct_ptr_array[i].status = false;

Replace two lines by
struct_ptr_array[i].id = i;
struct_ptr_array[i].status = false;

Related

Access violation error when trying to free an array

I'm currently working on structures for a personnal project. I'm trying to use dynamically-allocated bidimensionnal arrays, and then free the space they're taking. An error occurs when I try to free the allocated space.
I was able to narrow down the source of the issue down to the function I had set up to destroy my structures, but wasn't able to pinpoint the cause of the error within. More concerning is the fact that the error, an access violation, only triggers half of the time.
I've included the functions below, with a few comments. I'm sorry if I'm including too much code here, but I'm geniunely lost at words and do feel like the way I initialize the structures may have an impact on whether I'm destroying them correctly.
#include <stdio.h>
#include <stdlib.h>
typedef struct f_part f_part;
typedef struct field field;
//these are the structures I used:
//part of a field: includes a character and a color
struct f_part
{
char caractere;
short int color;
};
//field: points to a bidimensionnal array of f_part, and remember its size
struct field
{
int fsize_x;
int fsize_y;
f_part **fbody;
};
field* fieldInitialize(const int size_x, const int size_y) //this function seems to work correctly, I've mostly added it as an indicator
{
field* terrain = malloc(sizeof(*terrain));
if (terrain == NULL)
printf("fail1");
terrain->fsize_x = size_x;
terrain->fsize_y = size_y;
f_part* ptrToFPart = NULL;
terrain->fbody = malloc(sizeof(ptrToFPart) * size_x); //this is where I allocate the space for an array of pointers
if (terrain->fbody == NULL)
printf("fail2");
int i,j;
for (i = 0 ; i < size_x ; i++)
{
terrain->fbody[i] = malloc(sizeof(f_part) * size_y);
for (j = 0 ; j < size_y ; j++)
{
terrain->fbody[i][j].caractere = 'a';
terrain->fbody[i][j].color = 0;
}
}
terrain->fsize_x = size_x;
terrain->fsize_y = size_y;
return terrain;
}
void fieldDestroy(field* terrain) //this is the function that is supposed to destroy the object and free the memory, and fails
{
int i;
for (i = 0 ; i < terrain->fsize_x ; i++)
{
free(terrain->fbody[i]); //this part always goes well
}
printf("flag 1\n");
free(terrain->fbody); //this is where the access violation happens, when it does
printf("flag 2\n");
free(terrain); //this part goes well too
printf("flag 3\n");
}
int main()
{
field* testField = fieldInitialize(5, 5);
fieldDestroy(testField); //This is the function that fails. Sometimes.
return 0;
}
The error systematically happens on that second-to-last line, when I try to free the space allocated for the array of pointers. Except it doesn't always happen! Sometimes, I can free terrain->fbody, and everything goes well, but other times, I can't free the space.
The error I get is 0xC0000005, which apparently translates to "access violation". Which I understand would be common when dealing with dynamic memory allocation, but then why do I seem to get the error only half of the time?
Edit : Okay, so I've edited a bit of the code. Interestingly enough, while my Windows 10 would fail between flags 1 and 2, my Windows 7 fails between flags 2 and 3, and returns too a 0xC0000005 error. But again, only occasionally.
In C, you must precede structure names with struct. So your functions should be declared:
struct field* fieldInitialize( ... )
and your allocations should be
struct field* terrain = malloc(sizeof(struct field));
You could also define these structures as types:
typedef struct
{
int fsize_x;
int fsize_y;
struct f_part **fbody;
} field;

C: How to free a struct ** that contains fields which are char* and ENUM (int)?

My code contains the struct BeforeTriag which is from type Patient** .
here is the structs and it's fields:
typedef struct{
char Id[ID_SIZE];
char Name[NAME_SIZE];
char LastName[NAME_SIZE];
char PhoneNum[PHONE_SIZE];
STATUS Status;
char Address[ADDRESS_SIZE];
}Patient;
Here is my initilization and allocation:
Patient** BeforeTriag = NULL;
int* BeforeTriagSize[1] = { 0 };
BeforeTriag = (Patient**)malloc(sizeof(Patient*));
if (!(BeforeTriag))
{
printf("ERROR!Out of memory!");
exit(1);
}
*BeforeTriag = (Patient*)malloc((PatientArraySize)* sizeof(Patient));
if (!(*BeforeTriag)){
printf("ERROR!Out of memory!");
exit(1);
}
here i'm tring to free each field in the struct:
for (i = 0; i < (*BeforeTriagSize); i++){
free((BeforeTriag)[i]->Id);
free((BeforeTriag)[i]->Name);
free((BeforeTriag)[i]->LastName);
free((BeforeTriag)[i]->Address);
free((BeforeTriag)[i]->PhoneNum);
}
free(BeforeTriag);
When I am debugging it crush on the first row of the free id:
free((BeforeTriag)[i]->Id);
What should i do to free as proper?
The individual fields within BeforeTriag[i] were not dynamically allocated by themselves, so you can't free them. You need to free the struct as a whole, because that's what was allocated:
for (i = 0; i < (*BeforeTriagSize); i++){
free(BeforeTriag[i]);
}
free(BeforeTriag);
You do not have to do this:
for (i = 0; i < (*BeforeTriagSize); i++){
free((BeforeTriag)[i]->Id);
free((BeforeTriag)[i]->Name);
free((BeforeTriag)[i]->LastName);
free((BeforeTriag)[i]->Address);
free((BeforeTriag)[i]->PhoneNum);
}
Because they are not dynamically allocated.
But you have to free BeforeTriag[i] inside the loop.
for (i = 0; i < (*BeforeTriagSize); i++){
free(BeforeTriag[i]);
}
free(BeforeTriag);
While #dbush and #RolBrok already pointed out correctly that there's no need to free the individual members, there is another bug in your code:
int* BeforeTriagSize[1] = { 0 };
This line initalizes a int ** to zero. I'm not really sure why you want this variable to be in an array, but anyway, the correct way to declare it would be
int BeforeTriagSize[1] = { 0 };
(If you only need one value for BeforeTriagSize anyway, just declare it as an int!)
Edit:
Another thing you should look closer into is the way you're allocating memory for your structs:
*BeforeTriag = (Patient*)malloc((PatientArraySize)* sizeof(Patient));
With this you're always writing to the same pointer. So when you are allocating the memory for the second struct, you are overwriting the position of the first one, basically causing a memory leak.
Consider something along the line of
BeforeTriag[BeforeTriagSize++] = (Patient*)malloc((PatientArraySize)* sizeof(Patient));
This ensures that you are writing to a new position in your array every time. (Assuming you changed BeforeTriagSize to an int - if you need to hand it over as a pointer to some functions just use the address operator (&))

seg fault from 2d array allocation

i have a struct "cell" defined as
typedef struct{
int id;
terrainType terrain;
} cell;
i then make a 2d array of cells with
cell** makeCellGrid(int sizeX, int sizeY)
{
cell** theArray;
int i;
theArray = (cell**) malloc(sizeX*sizeof(cell*));
for ( i = 0; i < sizeX; i++)
{
theArray[i] = (cell*) malloc(sizeY*sizeof(cell));
}
return theArray;
}
at first i thought this was working fine but a few seg faults later i discovered that with some values (e.g. makeCellGrid(32, 87) ) it breaks.
im fairly fresh with C pointers and memory junk and was hoping some one could point me in the right direction here.
with lower number bounds i had no issue accessing it with
map[i][j].id = x;
and so on
EDIT: forgot to add, from testing, the seg fault originate from
theArray[i] = (cell*) malloc(sizeY*sizeof(cell));
The code lacks error checking for the malloc() system call.
So if the first call to malloc() failed the second one (in the loop) tries to assign memory to NULL which indeed leads to the segmentation violation your are witnessing.
You might consider modifing you code like so:
#include <stdlib.h>
typedef struct {
int id;
TerrainType terrain;
} CellType;
void freeCellGrid(CellType ** ppCells, size_t sizeX)
{
size_t i = 0;
for (; i < sizeX; ++i)
{
free(ppCells[i]);
}
free(ppCells);
}
CellType ** makeCellGrid(size_t sizeX, size_t sizeY)
{
CellType ** ppCells = malloc(sizeX * sizeof(*ppCells));
if (ppCells)
{
size_t i = 0;
for (; i < sizeX; ++i)
{
ppCells[i] = malloc(sizeY * sizeof(**ppCells));
if (NULL == ppCells[i])
{
freeCellGrid(ppCells, i);
ppCells = NULL;
break;
}
}
}
return ppCells;
}
Notes on my modifications:
Always check system calls for errors (in the case of malloc() on error NULL is returned)
Better use an unsigned type to access memory/array indicies; size_t is meant for this
In C there is no need to cast the value returned by a void * function like malloc()
Always try to initialise variables as soon as possible; un-initilaised variables very easily lead to "irrational" behaviour of the application
If working with pointers, it might be helpfull to 'code' the level of indirection into their names (I did this here by using the prefix pp to indicated that it's a 2-level indirection)
types are different from variables: One way to distinguish this is by starting type names using capitals (CellType) and variables using small letters (ppCells).
If allocating memory to a pointer and it matters that the size of the allocated memory some suits the pointer's type it's always more secure to use the (dereferenced) pointer itself as argument to the sizeof operator then some type. As the declaration of the pointer the memory is allocated to might be changed during develpment and the adjustment of the argument to malloc() will be forgotten. To cut it short: doing as I did is less error prone.
If encapsulating the dynamical creation of structures (including arrays) it is a could idea to also implement a method which de-allocates it (here: freeCellGrid()). Even better start of with coding this deallocator first, as then you have it by hand when coding the allocator's error handling (as shown for the second call to malloc()).

How can I Return an array from a function without using malloc?

I've been struggling with a simple task in C... (It's been a while.) I need to build a function that creates and resets an array of structs without using any memory allocation functions.
I originally designed it with malloc:
typedef struct {
int ..
int ..
} Branch;
Branch* createBranchList (int N)
{
Branch *List;
Branch reSet = {0}; // a zero'd Branch struct used for the resetting process
int i;
if(!(List=(Branch*)malloc(sizeof(Branch)*N))){
printf("Allocation error");
return NULL;
}
for(i=0; i<N; i++)
List[i] = reSet;
return List;
}
Now how can I do this without using memory allocation? Can I return a reference? I don't think so.
Thanks anyone for helping out.
Safe method (1):
Define a struct with an array member, then return that.
e.g.:
struct MyContainer {
Thing x[42];
};
MyContainer foo(void) {
MyContainer m;
m.x[0] = 5;
m.x[1] = 10;
...
return m;
}
Obviously, this method will not be possible if the array size is not known to the function at compile-time.
Safe method (2):
Have the caller pass in the array as an argument.
e.g.:
foo(Thing *things, int N) {
thing[0] = 5;
thing[1] = 10;
...
}
Unsafe method:
Declare a static local array, and return a pointer to that.
This "works" because a static array is not deallocated when it goes out of scope. But it's unsafe because the array will be overwritten next time you use the function (particularly bad in a multi-threaded scenario).
This method will also not be possible if the array size is not known to the function at compile-time.

Is valgrind right? Is the memory lost?

typedef struct Model
{
int recordId;
char *name;
}Model;
typedef struct ModelArray
{
//keeps the size that the array was initially create with. When more elements are needed
//we use this to add that many more elements
int originalSize;
//total number of elements that can be used
int elements;
//total number of elements used
int count;
//the actual array is stored here
Model *source;
}ModelArray;
void initModelArray(ModelArray *array, int numberOfElements)
{
array->originalSize = numberOfElements;
array->elements = numberOfElements;
array->count = 0;
array->source = malloc(sizeof(Model)*numberOfElements);//0 bytes in 3 blocks are definitely lost in loss record 1 of 65
}
void deallocModelArray(ModelArray *array)
{
if(array == NULL)
return;
array->elements = 0;
array->count = 0;
free(array->source);
array->source = NULL;
free(array);
}
main(int argc, const char * argv[])
{
ModelArray *models = malloc(sizeof(ModelArray));
initModelArray(models, 10);
deallocModelArray(models);
}
What is lost? Code looks fine to me. I'm sure I could say array->source = NULL first but it's not needed, right?
To deallocate these structures correctly, you need to do the following, in this order:
free(models->source);
free(models);
If you do anything else, you're leaking memory.
Edit:
OK, having seen the Model struct, you're probably leaking the names, or at least valgrind thinks you do because you deallocate the ModelArray structure, which contains a pointer to a Model structure, which contains a char* which you don't free first.
So:
int i;
for( i=0; i<models->originalSize; i++ ) {
if( models->source[i]->name != NULL ) {
free( models->source[i]->name );
}
}
free(models->source);
free(models);
And it would be a good idea to use calloc() instead of malloc() when allocating models->source in the first place. This will set all the name pointers to 0. Without this, the test for models->source[i]->name being non-NULL above might fail if name happens to contain some garbage (since using uninitialized memory produces undefined behavior.)
Er... Yes, the memory is lost. Of course, it is lost, since you "left out dealloc code"!
How could you possibly expect anyone to answer your question when you "left out dealloc code"? The very essence of your question is whether your dealloc code is correct or not. And you decided to leave it out?
On top of that, there quite a few thing that make little sense in your code. What is
typedef struct ModelArray {
...
Model *source;
...
} Model;
supposed to mean? Why are you typedefing struct ModelArray as Model? In fact, your code will not even compile, since Model * is used inside the struct, where it is not declared yet. You also use ModelArray type in your code, while in reality there's no such type. You have struct ModelArray, but not just ModelArray. The code you posted is not real code. Post real code, please. (Apparently it was supposed to be typedef struct ModelArray { ... } ModelArray; with Model defined elsewhere.)
Finally, as an unrelated note, // comments is a C99 feature. In C99 the function return type cannot be omitted (no "implicit int" rule in C99), meaning that you have to declare your main function as int main.

Resources