Serialize struct to byte array with pointer as struct member - c

I am trying to copy a byte array to my struct, then serialize my struct to a byte array again.
But, after I serialize my struct array, I cant get my data value (0x12, 0x34, 0x56) again, instead i get some rubbish data.
What is wrong here?
#pragma pack(push, 1)
typedef struct {
uint8_t length;
uint8_t *data;
} Tx_Packet;
#pragma pack(pop)
static void create_tx_packet(uint8_t *packet, uint8_t *src, int length);
int main(void)
{
uint8_t packet[32];
uint8_t data[] = { 0x12, 0x34, 0x56 };
create_tx_packet(packet, data, 3);
//i check using debugger, i cant get the data value correctly
//but i could get length value correctly
return 0;
}
static void create_tx_packet(uint8_t *packet, uint8_t *src, int length)
{
Tx_Packet *tx_packet = malloc(sizeof(*tx_packet ));
tx_packet->length = length;
tx_packet->data = (uint8_t *)malloc(length);
memcpy(tx_packet->data, src, length);
memcpy(packet, tx_packet, sizeof(*tx_packet));
}

Right now, your create_tx_packet() function copies a Tx_Packet struct created in the function to a uint8_t array. That struct contains the length and a pointer to the data, but not the data itself. It's actually not necessary to use the struct as an intermediate step at all, particularly for such a simple packet, so you could instead do:
static void create_tx_packet(uint8_t *packet, uint8_t *src, int length)
{
*packet = length; /* set (first) uint8_t pointed to by packet to the
length */
memcpy(packet + 1, src, length); /* copy length bytes from src to
the 2nd and subsequent bytes of
packet */
}
You still need to make sure packet points to enough space (at least length + 1 bytes) for everything (which it does). Since the version above doesn't dynamically allocate anything, it also fixes the memory leaks in your original (which should have freed tx_packet->data and tx_packet before exiting).
--
If you do want to use a struct, you can (since the data is at the end) change your struct to use an array instead of a pointer for data -- then extra space past the size of the struct can be used for the data, and accessed through the data array in the struct. The struct might be:
typedef struct {
uint8_t length;
uint8_t data[];
} Tx_Packet;
and the function becomes (if a temporary struct is used):
static void create_tx_packet(uint8_t *packet, uint8_t *src, int length)
{
/* allocate the temporary struct, with extra space at the end for the
data */
Tx_Packet *tx_packet = malloc(sizeof(Tx_Packet)+length);
/* fill the struct (set length, copy data from src) */
tx_packet->length = length;
memcpy(tx_packet->data, src, length);
/* copy the struct and following data to the output array */
memcpy(packet, tx_packet, sizeof(Tx_Packet) + length);
/* and remember to free our temporary struct/data */
free(tx_packet);
}
Rather than allocate a temporary struct, though, you could also use struct pointer to access the byte array in packet directly and avoid the extra memory allocation:
static void create_tx_packet(uint8_t *packet, uint8_t *src, int length)
{
/* Set a Tx_Packet pointer to point at the output array */
Tx_Packet *tx_packet = (Tx_Packet *)packet;
/* Fill out the struct as before, but this time directly into the
output array so we don't need to allocate and copy so much */
tx_packet->length = length;
memcpy(tx_packet->data, src, length);
}

If you use memcpy(packet, tx_packet, sizeof(*tx_packet)); you are copying the memory representation of tx_Packet into packet, starting with tx_packet->length.
Additionally when mallocating tx_packet that size should be sizeof(*packet)+sizeof(uint8_t) (length of packet plus length field)
And again when copying the tx_packet back to packet you are writing out of the boundaries of packet.
EDIT:
I forgot to mention that depending on your compiler memory alignment parameter you could get any length for the fields (including tx_packet->length) to accelerate memory operation. On 32bits machine it could be 4 and padded with rubbish.

When you serialize your struct with
memcpy(packet, tx_packet, sizeof(*tx_packet));
you're copying the length and the pointer to the data, but not the data itself. You'll probably need two memcpy calls: one of sizeof(uint8_t) to copy the length field, and one of length to copy the data.

This line:
Tx_Packet *tx_packet = malloc(sizeof(*packet));
only allocates one byte for the packet header, which you then immediately write off the end of, causing undefined behavior. You probably meant
Tx_Packet *tx_packet = malloc(sizeof(*tx_packet));

Related

How to extract N byte from offset x of uint8_t *bytes in c language?

How can i extract bytes from offset offset of tvb with length length length? type of tvb is :
uint8_t *tvb;
uint8_t *extractBytes(uint8_t *tvb, guint8 offset, guint8 length)
{
// do ...
// extract bytes and return
}
I don't know how can I do this ?
Thanks in advance.
You will need to allocate memory for the extracted bytes. Then it's a simple matter of copying the correct bytes:
uint8_t *extractBytes(uint8_t *tvb, guint8 offset, guint8 length)
{
uint8_t *new = malloc (length);
if (new) {
mempcy (new, tvb+offset, length);
}
return new; /* Returns NULL on allocation failure */
}
Don't forget to free() the allocated memory once you are done using it.
Note that the malloc() call above allocates length number of bytes. If you want to allocate memory for elements that are larger than uint8_t, you will have to multiply the amount by the size of the element. To be on the safe side, and to guard against future changes, you can allocate the memory as follows:
new = malloc (length * sizeof *new);
Now, sizeof *new will always be the correct element size.
If you don't need to change the extracted bytes, and the original buffer (tvb) doesn't change while you're using the bytes, you can access them directly using something like:
int i;
for (i = 0; i < length; i++) {
do_something (tvb[offset+i]);
}

Declare array in struct

I am trying to make a struct for a circular buffer that contains an array of type "quote." However, the quote array must start out at a size of 10. I am trying to figure out if I declare the size of 10 in my .h file or in my .c file. My two files are as follows:
.h file:
typedef struct{
unsigned int time;
double rate;
}quote;
typedef struct{
unsigned int testNum;
quote quoteBuffer[];
}cbuf;
cbuf* cbuf_init();
.c file:
cbuf* cbuf_init(){
cbuf *buffer = (cbuf *)calloc(1,sizeof(cbuf));
buffer->testNum = 1;
quote newQuote = {1,1.00};
buffer->quoteBuffer[1] = newQuote;
return buffer;
}
These are obviously just test values, however if I wanted to specifically make the quote array in the cbuf struct start out at a size of 10, would I declare that in the .h file as:
typedef struct{
unsigned int testNum;
quote quoteBuffer[10];
}cbuf;
or in the .c file some other way?
There are two ways of having dynamic arrays in structures. The obvious is of course to have it as a pointer, and dynamically allocate (or reallocate) when needed.
The other is to have an array of size 1, and then allocate a larger size than the structure, to accommodate for the array:
typedef struct {
unsigned int testNum;
quote quoteBuffer[1];
} cbuf;
cbuf *cbuf_init(const size_t num_quotes) {
/* Allocate for the `cbuf` structure, plus a number of `quote`
* structures in the array
*/
cbuf *buffer = malloc(sizeof(cbuf) + (num_quotes - 1) * sizeof(quote));
/* Other initialization */
return buffer;
}
/* If more quotes are needed after initial allocation, use this function */
cbuf *cbuf_realloc(cbuf *buffer, const size_t new_num_quotes) {
buffer = realloc(buffer, sizeof(cbuf) + (new_num_quotes - 1) * sizeof(quote));
/* Other initialization */
return buffer;
}
Now you can use the array as a normal array:
cbuf *buffer = cbuf_init();
buffer->quoteBuffer[5].time = 123;
Note: I only allocate extra space for 9 quote structures, but state that I allocate ten. The reason is that the cbuf structure already contains one quote structure in its array. 1 + 9 = 10. :)
Note 2: I put the quote array in the cbuf structure with one entry already in it for backwards compatibility. Having an array without a size in the structure is quite new in the C world.
you can also do this if you want 10 quotes in a cbuf but a statically allocated like quote buffer[10] would work too:
cbuf* cbuf_init(int numQuotes)
{
cbuf *b = calloc(1, sizeof(cbuf) + numQuotes * sizeof(quote));
return b;
}
If you want a statically sized circular buffer then your could declare the size in the header file. Using a #define for the buffer size will make the code more readable and maintainable, as you'll reference the size elsewhere in your code.
If you want the circular buffer to be growable then define the size in your C file. You'll then have to take care of tracking the size and destroying the memory that you will have to allocate dynamically.
In your example, I think you need to allocate more room for your quote structs...
cbuf *buffer = (cbuf *)calloc(1,sizeof(cbuf) + NUM_QUOTES*sizeof(struct quote));
---------------------------------
The reason for this is that in your struct def...
quote quoteBuffer[];
... quoteBuffer doesn't add size to the struct. quoteBuffer will point to one byte past the end of the struct, hence the need to allocate memory for the struct + memory for the array.
EDIT: Daniel Fischer's comment (thanks Daniel) - quoteBuffer may, in some cases, add size to the struct if it introduces padding. The reason is that the compiler will probably strive to get the most optimal alignment for quoteBuffer. For example, ints normally aligned of 4-byte boundaries. E.g. a struct like:
struct {
char a;
int b;
}
is probably changed by compiler to
struct {
char a;
char pad[3]; // compiler adds padding behind the scenes
int b; // align b on a 4-byte boundary
}
This probs doesn't apply in your case as your struct leaves quoteBuffer[] on a 4 byte boundary.
The reason that the compiler does this is two fold.
1. On some architectures (not so common nowadays I think?), unaligned accesses aren't supported.
2. Aligned accesses are more efficient, even if architecture allows non-aligned accesses as it is one memory read as opposed to two memory reads plus a manipulation.

How to allocate memory for a struct with char* member

My struct looks like this:
struct tlv_msg
{
uint8_t datatype; //type of data
/* data stored in a union */
union{
int32_t s32val; /* int */
int64_t s64val; /* long long */
uint32_t u32val; /* unsigned int */
uint64_t u64val; /* unsigned long long */
char* strval; /* string */
unsigned char* binval; /* any binary data */
};
uint32_t bytelen; /* no. bytes of union/data part */
};
This struct uses a union to hold some different data types. I have an alloc function which allocates memory for the struct on the heap. Am I correct in thinking that if I am allocating for an integral type (ie the first four types above in union) I only need to allocate as follows:
tlv_msg* msg = malloc(sizeof(tlv_msg));
sizeof(tlv_msg) returns 24. I presume this is enough bytes to hold the largest data type in the union plus the other data members. (not sure why 24 - can someone explain?).
But if the data type to be stored is a pointer type, eg char* then I then need to also do this:
msg->strval = (char*)malloc(sizeof(string_length+1);
That would make sense to me and that seems to work but just wanted to check.
That's perfectly right.
That said, you may want to create helper functions, to help you dealing with this.
For instance:
tlv_msg * new_tlv_msg( void );
/* There, you need to free struct members, if applicable */
void delete_tlv_msg( tlv_msg * msg );
/* Here you may copy your string, allocating memory for it */
tlv_msg_set_strval( tlv_msg * msg, char * str );
Implementation may be (basic, of course)
tlv_msg * new_tlv_msg( void )
{
return calloc( sizeof( tlv_msg ), 1 );
}
void delete_tlv_msg( tlv_msg * msg )
{
if( msg->strval != NULL )
{
free( msg-strval );
}
free( msg );
}
tlv_msg_set_strval( tlv_msg * msg, char * str )
{
if( msg->strval != NULL )
{
free( msg-strval );
}
msg->strval = strdup( str );
}
Yes, you are correct about having to perform two memory allocation steps, the first for the struct and the second for the character string.
Unless this is an embedded system where memory space is at a premium, one way to get around this is to decide on a maximum string size. Yes, that does waste memory, if, for example, you only usually have 10 character or fewer strings and allocate for say 25 characters.
#define WORKING_BUF_LEN 1024
struct tlv_msg
{
uint8_t datatype; //type of data
/* data stored in a union */
union{
int32_t s32val; /* int */
int64_t s64val; /* long long */
uint32_t u32val; /* unsigned int */
uint64_t u64val; /* unsigned long long */
char strval[WORKING_BUF_LEN={0}; /* string */
unsigned char* binval; /* any binary data */
};
uint32_t bytelen; /* no. bytes of union/data part */
};
You could also do your own memory management to avoid fragmenting the heap if you plan on having many of these structs and hence many char* pointers, but that requires a lot of work. You'd overwrite new with a macro and assign pre-allocated storage to your pointer and then do storage allocation book keeping. Don't do it unless you have to.

Structures with dynamic memory allocation in C

I need to write data into a structure where the length of the data depends on the command I want to send to a device. For that I have defined the following structure:
typedef struct {
uint8 len; // Command length (cmd ... crc)
uint8 cmd; // Command code
uint8 data_length; // Data length
uint8 data[12]; // Data: max 12 Byte
uint8 crc_h; // CRC value MSB
uint8 crc_l; // CRC value LSB
}CMD_TYPE;
Note: the members cmd, *data_length* and crc that are always present, instead member data can be empty or contains up to 12 Bytes.
I have created a function that returns a initialized command according to the parameters passed to the function:
CMD_TYPE Device::get_cmd(uint8 cmd, uint8 data_len, uint8 *data)
{
CMD_TYPE cmd;
cmd.len = (4 + data_len) * sizeof(uint8);
cmd.cmd = cmd;
cmd.data_length = data_len;
cmd.data = (uint8 *)realloc(cmd.data, data_len*sizeof(uint8));
if(data_len > 0) memcpy(cmd.data, data, data_len);
add_crc16((uint8*)&cmd);
return cmd;
}
The function get_cmd() is used like this:
uint8 cmd_code = 0x01;
uint8 data[2] = {0xAB, 0xCD};
CMD_TYPE cmd = local_device->get_cmd(cmd_code, 2, data);
retVal = local_device->send(cmd);
When I try to compile this code I get an error from the compiler for that line:
cmd.data = (uint8 *)realloc(cmd.data, data_len*sizeof(uint8));
and the compiler error is:
error: lvalue required as left operand of assignment
The aim of using realloc() is to re-size the array data or to remove it at all from my new command structure. What is wrong in my code? Is that the right way to initialize structures with dynamic memory allocation?
What you want is the infamous struct hack:
typedef struct
{
uint8 len; // Command length (cmd ... crc)
uint8 cmd; // Command code
uint8 data_length; // Data length
uint8 crc_h; // CRC value MSB
uint8 crc_l; // CRC value LSB
uint8 data[1]; // Data: max 12 Byte
} CMD_TYPE;
The trick is to allocate enough room for all of the members of the struct up to data[], then add enough bytes for the data[] member:
CMD_TYPE * allocCmd(int dataSize)
{
int len;
CMD_TYPE * p;
len = sizeof(CMD_TYPE) + (dataSize-1)*sizeof(uint8);
p = (CMD_TYPE *) malloc(len);
memset(p, 0, len);
p->data_length = dataSize;
return p;
}
Here, len is calculated to be the size of the struct, minus the size of the empty data member, plus however many elements dataSize specifies for the data array.
The catch is that you have to be careful never to access any elements of p->data[] beyond what is actually allocated in it (inside the struct).
Your CMD_TYPE.data is an array, not a pointer. Since you want it to track dynamically allocated memory, it has to be a pointer:
uint8_t * data;
Just don't forget to initialize it with malloc() (or by setting it to zero before realloc()) and to clean up after yourself
By the way, do not cast the result of malloc() and co.
array defined as a[..] are immutable, you can't assign anything to them. Instead you should use pointers.

Sending char pointer with UDP in C

I have a struct that I am sending to a UDP socket:
typedef struct
{
char field_id;
short field_length;
char* field;
} field_t, *field_p;
I am able to read the field_id and field_length once received on the UDP server-side, however the pointer to field is invalid as expected.
What is the best method to properly send and receive a dynamic char*?
I have a basic solution using memcpy on the client side:
char* data =
(char*)malloc(sizeof(field_t) + (sizeof(char) * strlen(my_field->field)));
memcpy(data, my_field, sizeof(field_t));
memcpy(data+sizeof(field_t), my_field->field, strlen(my_field->field) + 1);
And on the server side:
field_p data = (field_p)buffer;
field_string = (char*)buffer+sizeof(field_t);
Is there a cleaner way of doing this or is this the only way?
Thanks.
You of course cannot send a pointer over a socket - get rid of the char* field; member. Instead, just append id and size pair with the data itself. Use writev(2) or sendmsg(2) to avoid moving data around from buffer to buffer.
Watch out for structure member alignment and padding and number endianness.
Serialization is your friend.
Related Links:
SO-1
SO-2
Define your structure as:
typedef struct
{
uint8_t field_id;
uint16_t field_length;
char field[0]; // note: in C99 you could use char field[];
} field_t, *field_p;
Then, text buffer will immediately follow your structure. Just remember a few tricks:
// initialize structure
field_t *
field_init (uint8_t id, uint16_t len, const char *txt)
{
field_t *f = malloc (sizeof (field_t + len)); // note "+ len";
f->field_id = id;
f->field_length = len;
memcpy (f->field, txt, len);
return f;
}
// send structure
int
field_send (field_t *f, int fd)
{
return write (fd, f, sizeof (*f) + f->field_length); // note "+ f->field_length"
}
I don't think it's standard, though. However, most compilers (GCC && MSVC) should support this. If your compiler does not support zero-sized array, you can use one-element char array - just remember to subtract extra one byte when calculating packet size.

Resources