[英]Serialize struct to byte array with pointer as struct member
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. 但是,在我序列化我的struct数组后,我再也无法得到我的数据值(0x12,0x34,0x56),而是得到一些垃圾数据。
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. 现在,您的
create_tx_packet()
函数将函数中创建的Tx_Packet
结构复制到uint8_t
数组。 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:
实际上没有必要使用struct作为中间步骤,特别是对于这样一个简单的数据包,所以你可以改为:
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). 你仍然需要确保
packet
指向足够的空间(至少length + 1
个字节)来处理所有事情(它确实如此)。 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). 由于上面的版本没有动态分配任何东西,它还修复了原始内存泄漏(在退出之前应该释放
tx_packet->data
和tx_packet
)。
-- -
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. 如果你想使用结构,你可以(因为数据在最后)改变你的结构使用数组而不是
data
的指针 - 那么超出结构大小的额外空间可以用于数据,并通过struct中的data
数组进行访问。 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: 但是,您可以使用struct指针直接访问
packet
的字节数组,避免额外的内存分配,而不是分配临时结构:
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));
如果你使用
memcpy(packet, tx_packet, sizeof(*tx_packet));
you are copying the memory representation of tx_Packet
into packet, starting with tx_packet->length
. 您正在将
tx_Packet
的内存表示复制到数据包中,从tx_packet->length
。
Additionally when mallocating tx_packet that size should be sizeof(*packet)+sizeof(uint8_t)
(length of packet plus length field) 另外,当mallocating tx_packet时,该大小应该是
sizeof(*packet)+sizeof(uint8_t)
(数据包加长度字段的长度)
And again when copying the tx_packet
back to packet
you are writing out of the boundaries of packet
. 再次将
tx_packet
复制回packet
您正在写出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. 我忘了提到,根据你的编译器内存对齐参数,你可以获得字段的任何长度(包括
tx_packet->length
)来加速内存操作。 On 32bits machine it could be 4 and padded with rubbish. 在32位机器上它可以是4并用垃圾填充。
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. 您可能需要两个
memcpy
调用:一个用于复制长度字段的sizeof(uint8_t)
,另一个用于复制数据的length
调用。
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));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.