Free memory for elements of GArray - c

I create drvm *drv structure in my function. This structure itself contains fields which contains malloc()-ed fields (uint32_t *buffer). The code which do that is similar to that:
...
size_t elm_size = sizeof(model*);
uint32_t length = *(uint32_t*)len;
GArray *models = g_array_sized_new(FALSE, FALSE, elm_size, length);
model *mod;
for (int i = 0; i < length; ++i) {
mod = create_model(...);
g_array_append_val(models, mod);
}
This piece of code doesn't contain errors and is highly tested.
At the start of program I register function free_all() (by atexit()) which should clean all resources (especially memory) when exit() is performed.
Inside this function I'm trying freeing memory of elements of GArray* (model * structure) and memory for GArray * itself:
GArray *models;
g_array_set_clear_func(models, clean_model);
if(!g_array_free(models, FALSE)) { //OK }
The problem is that when clean_model(void *data) is called inside glib library I suggest it contains pointer to one model * element. But the address is wrong, it doesn't seem point to any correct value. Neither GArray*, nor model*.
Furthermore GArray *models in free_all() function is correct (the same as when I created it) and when I iterate through all GArray * elements in free_all() by
for (int i = 0; i < len; ++i) {
mod = g_array_index(models, model*, i); // Here I get correct pointer to model*
clean_model(mod);
}
I get expected values.
Question: What's wrong? How should I free memory of elements of GArray * if these elements contain malloc()-ed memory?
Part of header:
struct _info {
uint32_t *buffer;
uint32_t len;
};
typedef struct _info info;
struct _prod {
uint32_t *buffer;
uint32_t len;
};
typedef struct _prod prod;
struct _model {
uint32_t name;
prod product;
info inform;
};
typedef struct _model model;
struct _drvm {
GArray *models;
GArray *strings;
};
typedef struct _drvm drvm;

Basically the problem is that your clean_model function is passed model** instead of model* you were expecting.
Remember that GArray is meant to store complete structs, not just pointers to structs. In order to do that it needs to copy the whole contents of the struct into the internal data array and therefore any subsequent pointers to the structs (as passed to clean_model) are going to be pointing somewhere inside data (i.e. clean_model((elt_type*)&models->data[index * sizeof(elt_type)]) - where in your case elt_type is model*)
To fix the situation couple options come to mind, in order of (subjective) preference:
use GPtrArray instead; given that your elements are dynamically allocated already the memory management / pointer handling / typecasts (or lack thereof) would be less confusing
change clean_model argument to model**
use GArray to store model structs rather than pointers, but only makes sense if you can separate the allocation from populating the model contents, e.g. g_array_new(FALSE, FALSE, sizeof(model)) and fill_model(&g_array_index(models, model, i))
In all cases you should also probably pass TRUE to g_array_free since you don't seem to be using the GArray.data for anything afterwards (not that it would make any sense given that you're freeing all the useful data in it anyway.)

Related

Is it possible to leave fields unitialized using designated intiailizers?

Consider the following struct and function to create the struct:
#define MAX_ELEMS 1000
struct stuff {
double magic;
bool is_valid[MAX_ELEMS];
double values[MAX_ELEMS];
};
struct stuff make_stuff(double magic) {
return (struct stuff){
.magic = magic
};
}
In my case, I need stuff.magic to be intialized to the given value, and the stuff.is_valid array to be zero initialized, but I do not want to initialize stuff.values (as they are guarded by stuff.is_valid and initialized on-demand later).
Can I achieve this with designated initalizers?
I know I can achieve it without, but this is uglier and more error-prone (among other reasons, as I now need to explicitly zero stuff.is_valid, perhaps with a memset).
Any field not specifically initialized will be filled with zeros.
So, no, if you initialize any fields, they all get something (even if its just zeros)
It can only be done by "normal" assignments and memset.
struct stuff make_stuff(double magic)
{
struct stuff s;
memset(s.is_valid, 0, sizeof(s.is_valid));
s.magic = magic;
return s;
}
But if you are looking for the efficiency returning such a large struct makes no sense as it will me twice copied in full as structs are passed by the value
It is better to pass the pointer to the structure.
struct stuff *make_stuff(struct stuff *s, double magic)
{
memset(s -> is_valid, 0, sizeof(s -> is_valid));
s -> magic = magic;
return s;
}

How to send the properties of a struct array as a parameter to a function in C?

So here is my problem.
I have a struct that has some properties:
struct foo {
const uint8_t propertyA;
int propertyB;
const int propertyC;
typeX propertyD;
typeY propertyE;
};
I then create an array of this struct since I have to represent multiple instances of the object foo:
const int foosQuantity = 8;
struct foo foos[foosQuantity] =
{{ .propertyA=0b11001100, .propertyB=0, .propertyC=140, ...},
{ .propertyA=0b11001000, .propertyB=0, .propertyC=150 ...},
//*** foosQuantity-3 MORE TIMES ***//
{ .propertyA=0b11001000, .propertyB=0, .propertyC=150 ...}}
Until now everything seems to work. However, I have not figured how to send an array of one type of property to a function. For example, I Have this function written in an extern library that takes an array of propertiesA:
void myFunc(const uint8_t *propertyAs, sizeArray){
//*** DO STUFF ***//
}
And I would like to send the properties of my struct directly without having to use a for loop that iterates through the struct array and copies the elements.
int main(){
//*** STUFF ***//
myFunc(foos.propertyA, foosQuantity);
//*** MORE STUFF ***//
return 0;
}
Is this possible?
If the entire struct array already exists in your program's memory, you aren't going to get more efficient than just passing a pointer to the start of the array, the array's length (in elements), and iterating on the propertyA members of the array:
void bar(struct foo *p, size_t len)
{
size_t i;
for(i = 0; i < len; i++)
{
dosomething(p[i].propertyA);
}
}
If you are restricted by assigned specifications to only be allowed to pass an array of propertyA (i.e. uint8_t) to your function, you do have to copy them out of the array of struct foo; there's no way around that.
This is not possible.
You can either
Use a parallel array with just propertyA that gets manipulated along side the array of foo.
Or create an array of propertyA then copy it back in the foo array.
Option 1 is the most memory efficient since it requires the least memory but it may require you to rewrite your a lot of your code.
Option 2 requires the least amount of rework of your code but requires more memory and time.

C same structure different size

My question is related to this one :
c define arrays in struct with different sizes
However, I do NOT want to use dynamic allocation (embedded target).
Problem recap :
In C, I want to have two versions of the same structure, each one with a different size for its static arrays.
Both the structures will be used by the same functions through pointer parameter.
typedef struct {
short isLarge; //set 0 at initialization
short array[SIZE_A];
//more arrays
} doc_t;
typedef struct {
short isLarge; //set 1 at initialization
short array[SIZE_B];
//more arrays
} doc_large_t;
void function( doc_t* document ) {
if ( document->isLarge ) {
//change document into doc_large_t* [1]
}
//common code for both doc_t and doc_large_t
}
Questions :
(1) The above description needs a way to dynamically cast the pointer doc_t* pointer to doc_large_t* document [1]. Is that possible ? How ?
(2) An other solution i came with is to have a common header data part for both structure, including not only the isLarge flag, but also the pointers to the following static arrays. How ugly is that ?
(3) Also, do you have a good trick or workarround I could use ?
EDIT :
More context :
My application is a path finding on an embedded MCU.
I have geometrical objects, like polygons. Polygons can describe simple rectangular obstacles, as well as more complex shapes (such as the accessible area).
Complex polygons can have a huge amount of vertices, but are in small quantity. Simple polygons are very common.
Both will use the same algorithms.
I know in advance which polygon will need more vertices.
What I am trying to do is to optimize working memory to make it fit into the MCU. (i.e. small shapes get small arrays; complex ones get large arrays)
Idea similar to what you mentioned in your question already (pointers to arrays), but with only one single pointer:
typedef struct
{
short array[SIZE_B - SIZE_A];
// more arrays alike...
} Extension;
typedef struct
{
short array[SIZE_A];
//more arrays (all the small ones!)
Extension* extraData;
} doc_t;
If extraData is NULL, you have a small polygone, otherwise, you find the additional data in the struct referenced. Admitted, iterating over all values for large polygons gets a little nasty...
If you can use global arrays of predefined size for each object type (as Dominic Gibson proposed - a good proposition, by the way), you could spare the isLarge flag by replacing it with a function:
int isLarge(void* ptr)
{
return
(uintptr_t)globalLargeArray <= (uintptr_t)ptr
&&
(uintptr_t)ptr < (uintptr_t)globalLargeArray + sizeof(globalLargeArray);
}
Of course, all polygons (in above case: the large ones at least) would have to live in this array to make it work. If you create at least one dynamically or otherwise elsewhere (stack, another global variable) - we are out...
Create the arrays globally and use a pointer pointig to the big or small array.
You should try to keep a single structure and for the different array sizes put them in an union. I don't know whether the following structure would make sense to your case.
typedef struct {
short isLarge; //manually set to 0 or 1 after creating structure
//and accordingly initialize the arrays in below union
union my_varying_arrays {
short array_A[SIZE_A];
short array_B[SIZE_B];
};
//more arrays
} doc_t;
If isLarge is 0, set the value for array_A array and if 1 set the value for array array_B.
You can do this is the data is const by using a void * to the specific array.
Then you just cast the void * to what you need it to be depending on the attributes in the structure.
It becomes more complicated when you need the structures in runtime.
Especially on embedded targets.
typedef struct {
short size;
void *array;
} doc_t;
Where array points to a memory block allocated by the memory manager.
You now have to decide whether to use C standard malloc or use some pooled memory system based on the largest block size.
An example would be ChibiOS Memory pools.
If you are allocating and freeing variable sized memory blocks at random you risk memory fragmentation.
If you allocate incrementally you don't have to worry about much about memory. Just create one large block and keep track of where you are. A bit like a stack.
After the edit, I think the best thing you can do is to profile your needs defining max simple and complex polygons your target can manage and then declare a pool of simplex and common polygons, like:
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#define MAX_COMPLEX 16
#define MAX_SIMPLE 16
uint16_t g_Simple_Poly_set[MAX_COMPLEX][SIZE_A];
uint16_t g_Complex_Poly_set[MAX_COMPLEX][SIZE_B];
uint16_t g_Simple_Poly_used = 0;
uint16_t g_Complex_Poly_used = 0;
struct poly
{
bool isLarge;
uint16_t *vetexes;
};
bool create_poly_simple (struct poly *p)
{
bool retVal = false; // default: not more space for poly
if (g_Simple_Poly_used < MAX_SIMPLE)
{
p->isLarge = false;
p->vetexes = &g_Simple_Poly_set[g_Simple_Poly_used][0];
g_Simple_Poly_used++;
retVal = true;
}
return retVal;
}
bool create_poly_compleX (struct poly *p)
{
bool retVal = false; // default: not more space for poly
if (g_Complex_Poly_used < MAX_COMPLEX)
{
p->isLarge = true;
p->vetexes = &g_Complex_Poly_set[g_Complex_Poly_used][0];
g_Complex_Poly_used++;
retVal = true;
}
return retVal;
}
void your_stuff_with_poly ( struct poly *p)
{
uint32_t poly_size = (p->isLarge == false) ? SIZE_A : SIZE_B;
// your stuff with the correct size
}
This is a simple implementation designed for a static "instantiation" of structs. You can also enhance the code with a create/destroy function that trace which array into pool is free to be used.
Your number 2 solution is the right idea. It's unclear to me why you think that is ugly. Maybe this beautiful implementation will change your mind.
You can implement single inheritance is C by placing the base structure as the first member of the inheriting structure. Then inheriting objects can be referenced with a pointer to the base type.
typedef struct {
short doc_type;
short *array_ptr;
// more array pointers
} doc_base_t;
typedef struct {
doc_base_t base; // base.doc_type set 0 at initialization
short array[SIZE_A]; // base.array_ptr initialized to point here
//more arrays
} doc_small_t;
typedef struct {
doc_base_t base; // base.doc_type set 1 at initialization
short array[SIZE_B]; // base.array_ptr initialized to point here
//more arrays
} doc_large_t;
void function( doc_base_t* document ) {
if ( document->doc_type == 1) {
// array size is large
} else {
// array size is small
}
//common code referencing arrays through doc_base_t->array_ptr
}
The array_ptr member in doc_base_t isn't necessary for the inheritance mechanism. But I added that specifically for the "common code" portion of your function. If doc_base_t didn't include the array_ptr then you could cast the generic document to either adoc_small_t or doc_large_t type based upon the base_type value. But then you might need a different implementation for each inherited type. By adding the array_ptr member to doc_base_t I suspect you could write a common implementation for all inherited types.
So you will statically declare all your instances of doc_small_t and doc_large_t. And you'll initialize both the base.doc_type and base.array_ptr members when initializing each object. Then you will cast both types of objects to doc_base_t before calling function. (Or pass the address of the base member, which results in the same pointer value.)
Updated example:
static doc_small_t doc_small_instances[NUM_SMALL_INSTANCES];
static doc_large_t doc_large_instances[NUM_LARGE_INSTANCES];
// DocInit must be called once at startup to initialize all the instances.
void DocInit()
{
int index;
for (index = 0; index < NUM_SMALL_INSTANCES; index++)
{
doc_small_instances[index].base.doc_type = SMALL;
doc_small_instances[index].base.array_ptr = doc_small_instances[index].array;
}
for (index = 0; index < NUM_LARGE_INSTANCES; index++)
{
doc_large_instances[index].base.doc_type = LARGE;
doc_large_instances[index].base.array_ptr = doc_large_instances[index].array;
}
}
// DocProcess processes one doc, large or small.
void DocProcess(doc_base_t *document)
{
int index;
short *array_member_ptr = document->array_ptr;
int array_size = SMALL;
if (document->doc_type == LARGE)
{
array_size = LARGE;
}
for (index = 0; index < array_size; index++)
{
// Application specific processing of *array_member_ptr goes here.
array_member_ptr++;
}
}
// ProcessAllDocs processes all large and small docs.
void ProcessAllDocs(void)
{
int index;
for (index = 0; index < NUM_SMALL_INSTANCES; index++)
{
DocProcess(&doc_small_instances[index].base);
}
for (index = 0; index < NUM_LARGE_INSTANCES; index++)
{
DocProcess(&doc_large_instances[index].base);
}
}
It's easy with malloc() or similar dynamic allocation methods. Just use a flexible array member:
typedef struct {
short isLarge; //set 0 at initialization
.
.
.
short array[SIZE_A];
short largeArray[];
} doc_t;
To allocate a "small structure":
doc_t *small = malloc( sizeof( *small ) );
small->isLarge = 0;
To allocate a "large structure":
doc_t *large = malloc( sizeof( *large ) + ( SIZE_B - SIZE_A ) * sizeof( large->largeArray[ 0 ] );
large->isLarge = 1;
Note that you must keep the largeArray element last, which means that the array element must be next-to-last for this to work.
Depending on how you do your own allocation, this may or may not be applicable.
(It's also a bit of a hack, since it depends on being able to access data in largeArray by using an index of SIZE_A or greater on array. That's accessing an object outside its bounds...)

Dynamically allocated array of structures in C

I just wanted to know if the following works. I have a struct
called foo that is defined as the following:
struct foo {
char name[255];
int amount;
};
During runtime, I need to create an array of the above structures whose size is dependent on a value I receive from a file's input. Let's say this size is k. Will the following code appropriately allocate a dynamically-sized array of structures?
struct foo *fooarray;
fooarray = malloc(k * sizeof(struct foo));
EDIT: If I want to access members of the structures within these arrays, will I use the format fooarray[someindex].member?
That will work (and your accessing is correct). Also, you can guard against size errors by using the idiom:
fooarray = malloc(k * sizeof *fooarray);
Consider using calloc if it would be nice for your items to start out with zero amounts and blank strings, instead of garbage.
However, this is not a VLA. It's a dynamically-allocated array. A VLA would be:
struct foo fooarray[k];
Yes it will.
On failure it will return 0.
And you have to free the memory returned by malloc when you are done with it
You can access the first member:
fooarray[0].name
fooarray[0].amount
The second as:
fooarray[1].name
fooarray[1].amount
etc..
One more different notation can be used in this approach:
struct foo {
char name[255];
int amount;
};
int main (void)
{
struct foo *fooarray;
struct foo *fooptr[5];
unsigned int i = 0;
for (i = 0; i < 5; i++)
fooptr[i] = malloc(1* sizeof(struct foo));
fooptr[2]->name[3] = 'A';
printf ("\nfooptr[2]->name[3]=%c\n",fooptr[2]->name[3]);
}

How to correctly define an array of structures?

i have the following structure:
typedef struct Course {
int course_id;
char* course_name;
int prior_course_id;
StudentTree* students;
} Course;
and the following function i need to implement:
void createReport(FILE* courses[], int numOfCourses, FILE* studentFile, char* reportFileName
as you can see i get an array of FILE*, each cell contains different file pointer.
my intention is to create an array that each cell is Course* type, and initialize each cell with a Course struct containing the data read from the courses files.
what is the correct way to declare it inside the function?
do i need to dynamically allocate memory for it, or it can be done in compilation?
i've tried
Course* course_array[numOfCourses] = {NULL};
Course* course_array[numOfCourses] = NULL;
but it won't compile.
thanks for your help
You declare an array of structs the same way you declare an array of ints or FILE *s:
Type variableName[numberOfElements];
Before C99 (and barring compiler specific extensions), creating an array with a variable number of elements on the stack wasn't supported. So make sure that you are targeting the correct standard. In your case, assuming C99 support, the following should work:
Course *course_array[numOfCourses];
Because you intend to initialize each of the elements in the array, there is no need to zero them out.
You would then access the elements like this:
course_array[0] = malloc(sizeof(Course))
course_array[0]->course_id = 2;
/* etc. */
Now if you can't assume C99 support, things get a bit more tricky but not much:
Course *course_array = malloc(sizeof(Course *) * numOfCourses);
After that you can access course_array with the same array notation:
course_array[0] = malloc(sizeof(Course))
course_array[0]->course_id = 42;
/* etc. */
Once you're doing with the array, you'll need to make sure that you free any of the memory that you allocated:
for (i = 0; i < numOfCourses; i++) {
free(course_array[i]);
}
/* If you malloc'd course_array, then you need this too */
free(course_array);
Course* course_array[numOfCourses] = {NULL};
This is good, but it creates array of Course *. So you need to allocate memory for each pointer in course_array before accessing it.
Something like
course_array[0] = malloc(sizeof(Course));
course_array[0]->course_id = someid;
When you define the array in the first place, you shouldn't need to allocate memory. You're defining the array on the stack, and the elements of the array are just pointers.
I think what you should do is first define the array, and then initialize each element with a malloc call. For example:
Course* course_array[numOfCourses];
for(int i = 0; i < numOfCourses, i++) {
course_array[i] = (Course*)malloc(sizeof(Course));
My favorite way:
typedef struct {
int a;
char b;
float c;
}DATA;
//then use typdef'ed DATA to create array (and a pointer to same)
DATA data[10], *pData;
//then, in function, you can initialize the pointer to first element of array this way:
int main(void)
{
pData = &data[0];
return 0;
}
Your example code would look like this:
typedef struct {
int course_id;
char* course_name;
int prior_course_id;
StudentTree* students;
} COURSE;
//then in function:
COURSE course[numOfCourses]

Resources