This struct is supposed to have the infos for each item of a queue.
struct tx_queue_item_t {
//user input
uint8_t priority;
uint8_t attempts;
uint8_t *buff;
size_t size;
uint32_t timeout; //10ms base
//system input
uint8_t idNum;
uint8_t attemptCount;
uint32_t tickCountAtTx; //to check for receive timeout
enum tx_queue_status_t status;
};
I would like to know if I'm able to have 'temporary items' (temporary structs), which free their own memory usage when such item of the queue be considered as done/processed.
Is there a way to make this in C? malloc?
Consider that I also want to access the values of variables by their names for each struct instance.
And also in order I can know what is the total memory being used for such purpose (create temporary items).
Regards.
No. C does not have widely-implemented garbage collectors. You can use an external library like boehm-gc, but that may not be what you want.
The most portable solution would be to use malloc and free manually, or use a function to create and destroy your structure.
Related
I have a huge buffer allocated with malloc on the heap, i want to write a custom allocator to allocate space from that buffer.
My question is now, if there's a way to "mark" some regions as "allocatable", "writable" and "reserved" in that buffer, like in Kernel Development.
An example, we've a buffer with 6 elements, how could i mark elements 2-5 as "reserved"?
[0][1][2][3][4][5]
Could it be possible with flags, a Bit Manipulation or something?
Or could i mark the pointer?
You could use something as simple as an array of struct (or a linked list) that includes a flag in each instance that you can set to indicate allocation allowed, or not.
For example, using a flag and ambiguous typing (void *):
typedef struct {
BOOL alloc; //set TRUE to allow or FALSE to disallow further allocation
void *space;
//other members
}BUF;
Create an array of BUF, and set the alloc member to TRUE or FALSE to set an instance be no longer accessible to changing its memory. Of course this would occur after initial memory had been allocated during initialization.
Or another possibility using enum of types, in conjunction with a union:
typedef enum {
_INT,
_UINT,
_CHAR,
_UCHAR,
... //other types
}TYPE;
typedef struct {
BOOL alloc; //set to allow or disallow further allocation
TYPE type; //flag to track type being used in instance
union {
char *cMem;
unsigned char *ucMem;
int *iMem;
unsigned int *uiMem;
... // other members
char *space;
}BUF;
Convert number of buffers in to bit array of unsigned int and use index of memory to mark it.
E.g.: unsigned int allocatable [((x) +31)>>5];
similar for writable and reserved.
What is the best/fastest way ?
Struct of struct:
struct Sheet{
u8 status; // to check if empty ?
u8 reserve0;
u8 reserve1;
u8 reserve2;
struct words words[1024];
};
struct Book {
int id;
struct Sheet sheet[64];
};
In this case, how to check if the sheet table is empty or not ? I need to add a status for each sheet ?
or
Pointer table of struct
struct Sheet{
u8 reserve0;
u8 reserve1;
u8 reserve2;
struct words words[1024];
};
struct Book {
int id;
struct Sheet* sheet[64];
};
I don't need to use malloc since they are fixed table.
In the struct of struct, I can initialize by setting status but for pointer to struct, I can initialize with bookinstance.sheet[] = NULL or something like this.
I am pretty lost with pointers, struct and malloc. I come from Ruby...
To be clear:
I want not more than 64 sheet in my book instance. Maybe only 3 will be used or 64... But I want to be able to add them and check them with a number from 0 to 63.
To a certain extent it depend on what you mean by "faster".
How your code will interact with these elements will change that. In general; however, there are very few times you would likely see any significant effect of CPU time.
Note that in option 2 Book only allocates an array of pointers so you will have to add code (and overhead) to allocate Sheets for the pointers to point to.
The first option would seem cleaner as long as you are not intending on some Sheets to be shared among books.
Also, if you are copying books, option 2 would be faster since you would only be copying pointer rather then the entire Sheet struct.
struct {
uint16 msg_length;
uint8 msg_type;
ProtocolVersion version;
uint16 cipher_spec_length;
uint16 session_id_length;
uint16 challenge_length;
V2CipherSpec cipher_specs[V2ClientHello.cipher_spec_length];
opaque session_id[V2ClientHello.session_id_length];
opaque challenge[V2ClientHello.challenge_length;
} V2ClientHello;
Is it possible to do something similar to the above (https://www.rfc-editor.org/rfc/rfc5246)? If so how do I go about coding this inside C?
To be more specific this line in the struct:
V2CipherSpec cipher_specs[V2ClientHello.cipher_spec_length];
Uses:
> V2ClientHello.cipher_spec_length
Which is defined in the same struct, to set the length of the array.
C does not support dynamic-sized arrays. To achieve your goal, you can use a pointer of type V2CipherSpec as structure variable and allocate memory at a later stage using the V2ClientHello.cipher_spec_length value.
Absolutely not. C does not have dynamic-size arrays. Instead, we can rely on tricks like this:
struct {
uint16 msg_length;
uint8 msg_type;
ProtocolVersion version;
uint16 cipher_spec_length;
uint16 session_id_length;
uint16 challenge_length;
char extra[0]; // or 1 if your compiler hates this
} V2ClientHello;
Then, do not create instances of this struct directly, but rather via malloc():
struct V2ClientHello* hello = malloc(sizeof(V2ClientHello) +
len1*sizeof(V2CipherSpec) + len2 + len3);
Now you have a dynamically-allocated structure of the size you need. You can make accessor functions to get the "extra" fields:
V2CipherSpec* get_spec(V2ClientHello* hello, int idx) {
assert(idx < hello->cipher_spec_length);
return ((V2CipherSpec*)&hello->extra)[idx];
}
And of course you can wrap up the malloc() call inside a create routine which takes the sizes of all three dynamic parts and does everything in one place for robustness.
The shown code from the RFC is pseudo code, you can not implement it as shown.
You need to allocate these arrays manually depending on V2ClientHello.cipher_spec_length and the other length specification fields, once their values are known.
Value of "V2ClientHello.cipher_spec_length" is not available at compile time. You can not specify the size of an array at run time, instead use:
V2CipherSpec *cipher_specs;
in struct and use malloc or calloc to allocate a block of memory at run time.
V2ClientHello.cipher_specs = (V2CipherSpec *)malloc(V2ClientHello.cipher_spec_length);
In the embedded world we often have data structures that are passed around via fixed-length buffers. These are relatively easy to handle using something like this:
#define TOTAL_BUFFER_LENGTH 4096
struct overlay {
uint16_t field1;
uint16_t field2;
uint8_t array1[ARY1_LEN];
};
static_assert(sizeof(struct overlay) <= TOTAL_BUFFER_LENGTH);
struct overlay* overlay = malloc(TOTAL_BUFFER_LENGTH);
That is, we use a data structure as an overlay to allow easy access to the part of the buffer that is currently being used.
We have a number of buffer formats, however, that also use the last few bytes of the buffer to store things like checksums. We currently use constructions like this:
struct overlay {
uint16_t field1;
uint16_t field2;
uint8_t array1[ARY1_LEN];
char reserved[TOTAL_BUFFER_LENGTH -
sizeof(uint16_t) - sizeof(uint16_t) -
(sizeof(uint8_t) * ARY1_LEN) -
sizeof(uint32_t)];
uint32_t crc;
};
As ugly as this looks for this simple data structure, it's an absolute monstrosity when the structure grows to have dozens of fields. It's also a maintainability nightmare, as adding or removing a structure field means that the size calculation for reserved must be updated at the same time.
When the end of the structure only contains one item (like a checksum), then we sometimes use a helper function for reading/writing the value. That keeps the data structure clean and maintainable, but it doesn't scale well when the end of the buffer has multiple fields.
It would help greatly if we could do something like this instead:
struct overlay {
uint16_t field1;
uint16_t field2;
uint8_t array1[ARY1_LEN];
char reserved[TOTAL_BUFFER_LENGTH -
offsetof(struct overlay, reserved) -
sizeof(uint32_t)];
uint32_t crc;
};
Unfortunately, offsetof only works on complete object types and since this is in the middle of the definition of struct overlay, that type isn't yet complete.
Is there a cleaner, more maintainable way to do this sort of thing? I essentially need a fixed-length structure with fields at the beginning and at the end, with the remaining space in the middle reserved/unused.
In your situation, I think I'd probably do things this way:
typedef struct overlay_head
{
uint16_t field1;
uint16_t field2;
uint8_t array1[ARY1_LEN];
} overlay_head;
typedef struct overlay_tail
{
uint32_t crc;
} overlay_tail;
enum { OVERLAY_RSVD = TOTAL_BUFFER_LENGTH - sizeof(overlay_head)
- sizeof(overlay_tail) };
typedef struct overlay
{
overlay_head h;
uint8_t reserved[OVERLAY_RSVD];
overlay_tail t;
} overlay;
You can then work almost as before, except that where you used to write p->field1
you now write p->h.field1, and where you used to write p->crc you now write p->t.crc.
Note that this handles arbitrarily large tail structures quite effectively, as long as the head and tail both fit inside the overall size.
You could define a structure that simply has the buffer with a CRC field at the end:
struct checked_buffer {
char data[TOTAL_BUFFER_LENGTH - sizeof(uint32_t)];
uint32_t crc;
};
and then place your "overlays" on its data field. You're presumably already casting pointers to "convert" a raw buffer's char* into an overlay*, so it shouldn't be a big deal to cast from overlay* to checked_buffer* when you want to access the CRC field.
But if you want to have a field in a consistent position across a bunch of structures, it'd be easier to put it at the beginning of each structure. That way you can declare it directly in each structure without needing to do anything strange, and you don't need any pointer casts to access it.
How about that?
union a256
{
struct
{
int field_a;
int field_b;
char name[16];
//
int crcshadow;
};
struct
{
char buff[256-sizeof(int)];
int crc;
};
} ;
static_assert(offsetof(a256, crcshadow) < offsetof(a256, crc), "data too big");
The first struct contains data, the second define fixed size for this union.
I was wanting a simple string table that will store a bunch of constants and I thought "Hey! Lua does that, let me use some of there functions!"
This is mainly in the lstring.h/lstring.c files (I am using 5.2)
I will show the code I am curious about first. Its from lobject.h
/*
** Header for string value; string bytes follow the end of this structure
*/
typedef union TString {
L_Umaxalign dummy; /* ensures maximum alignment for strings */
struct {
CommonHeader;
lu_byte reserved;
unsigned int hash;
size_t len; /* number of characters in string */
} tsv;
} TString;
/* get the actual string (array of bytes) from a TString */
#define getstr(ts) cast(const char *, (ts) + 1)
/* get the actual string (array of bytes) from a Lua value */
#define svalue(o) getstr(rawtsvalue(o))
As you see, the data is stored outside of the structure. To get the byte stream, you take the size of TString, add 1, and you got the char* pointer.
Isn't this bad coding though? Its been DRILLED into m in my C classes to make clearly defined structures. I know I might be stirring a nest here, but do you really lose that much speed/space defining a structure as header for data rather than defining a pointer value for that data?
The idea is probably that you allocate the header and the data in one big chunk of data instead of two:
TString *str = (TString*)malloc(sizeof(TString) + <length_of_string>);
In addition to having just one call to malloc/free, you also reduce memory fragmentation and increase memory localization.
But answering your question, yes, these kind of hacks are usually a bad practice, and should be done with extreme care. And if you do, you'll probably want to hide them under a layer of macros/inline functions.
As rodrigo says, the idea is to allocate the header and string data as a single chunk of memory. It's worth pointing out that you also see the non-standard hack
struct lenstring {
unsigned length;
char data[0];
};
but C99 added flexible array members so it can be done in a standard compliant way as
struct lenstring {
unsigned length;
char data[];
};
If Lua's string were done in this way it'd be something like
typedef union TString {
L_Umaxalign dummy;
struct {
CommonHeader;
lu_byte reserved;
unsigned int hash;
size_t len;
const char data[];
} tsv;
} TString;
#define getstr(ts) (ts->tsv->data)
It relates to the complications arising from the more limited C language. In C++, you would just define a base class called GCObject which contains the garbage collection variables, then TString would be a subclass and by using a virtual destructor, both the TString and it's accompanying const char * blocks would be freed properly.
When it comes to writing the same kind of functionality in C, it's a bit more difficult as classes and virtual inheritance do not exist.
What Lua is doing is implementing garbage collection by inserting the header required to manage the garbage collection status of the part of memory following it. Remember that free(void *) does not need to know anything other than the address of the memory block.
#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked
Lua keeps a linked list of these "collectable" blocks of memory, in this case an array of characters, so that it can then free the memory efficiently without knowing the type of object it is pointing to.
If your TString pointed to another block of memory where the character array was, then it require the garbage collector determine the object's type, then delve into its structure to also free the string buffer.
The pseudo code for this kind of garbage collection would be something like this:
GCHeader *next, *prev;
GCHeader *current = firstObject;
while(current)
{
next = current->next;
if (/* current is ready for deletion */)
{
free(current);
// relink previous to the next (singly-linked list)
if (prev)
prev->next = next;
}
else
prev = current; // store previous undeleted object
current = next;
}