我需要序列化一个结构,我正在尝试使用memcpy做到这一点。但这是行不通的。通过查看字节流可以看出-我看到了垃圾字符。为什么?
我也得到运行时错误:
运行时检查失败#2-变量“地址”周围的堆栈已损坏。
发生了什么事,我该如何解决?
我正在使用#pragma pack(push, 1)
,我认为这将意味着不会填充结构。
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#pragma pack(push, 1) /* padding has to be disabled for casting to struct to work at other end */
typedef struct {
uint8_t start_char;
uint8_t msg_type;
uint8_t length;
} MSG_HEADER;
typedef struct {
uint8_t denomination[6];
uint8_t path;
uint8_t min_level;
uint16_t max_level;
uint16_t weight;
uint8_t address;
} CONFIG_DATA;
typedef struct {
MSG_HEADER header;
uint8_t clear_type;
CONFIG_DATA config_data[12];
uint8_t system_algorithm;
uint8_t max_transaction;
} MSG_CONFIGURATION;
#pragma pack(pop) /* only affect this file */
typedef struct {
unsigned char data[256];
size_t length;
int msg_type;
} TCHU_MESSAGE;
enum DRM_MESSAGE_TYPE {
CONFIG, CLEAR_COUNT, DISPENSE, CANCEL_TRANSACTION };
void TestCopy()
{
MSG_CONFIGURATION config;
config.clear_type = 0;
config.system_algorithm = 0;
config.max_transaction = 17;
const int NumItems = 12;
const uint16_t maxLevel = 300;
static const char* denoms[] = { "GB005A","GB005B","GB010A","GB010B",
"GB020A","GB050A","GB050B","GB100A",
"GB100B","GB200A", "EU100A", "EU100B" };
const uint8_t addresses[] = { 0, 0, 5, 5, 0, 7, 7, 8, 8, 9, 0, 0 };
const uint8_t sorting_paths[] = { 5, 5, 4, 4, 5, 2, 2, 1, 1, 3, 0, 0 };
for(int i = 0; i < NumItems; ++i) {
memcpy(config.config_data[i].denomination, denoms[i], 6);
config.config_data[i].address = addresses[i];
config.config_data[i].path = sorting_paths[i];
config.config_data[i].min_level = 3;
config.config_data[i].max_level = maxLevel;
config.config_data[i].weight = 1000;
}
config.header.start_char = 1;
config.header.msg_type = 2;
config.header.length = sizeof(MSG_CONFIGURATION);
TCHU_MESSAGE tchu_msg = {0};
// why does the memcpy not work? How can I get it to work?
memcpy(tchu_msg.data, &config+sizeof(MSG_HEADER), sizeof(MSG_CONFIGURATION) - sizeof(MSG_HEADER));
printf("sizeof(MSG_HEADER) = %u\n", sizeof(MSG_HEADER));
printf("sizeof(MSG_CONFIGURATION) = %u\n", sizeof(MSG_CONFIGURATION));
// get garbage in copyconfig
MSG_CONFIGURATION copyconfig;
memcpy(©config+sizeof(MSG_HEADER), tchu_msg.data, sizeof(MSG_CONFIGURATION) - sizeof(MSG_HEADER));
if(copyconfig.header.start_char != config.header.start_char)
{
// we get to here
printf("mismatch between original and copy\n");
}
}
int main() {
TestCopy();
// I also get Run-Time Check Failure #2 - Stack around the variable 'addresses' was corrupted.
// when program ends
}
最佳答案
我的编译器立即告诉我出了什么问题:
warning: '__builtin___memcpy_chk' will always overflow destination buffer [-Wbuiltin-memcpy-chk-size]
memcpy(©config+sizeof(MSG_HEADER), tchu_msg.data, sizeof(MSG_CONFIGURATION) - sizeof(MSG_HEADER));
这是为什么?好吧,让我们看一下目的地:
©config + sizeof(MSG_HEADER)
这意味着“获取
copyconfig
的地址,将其视为数组,并获取第N个对象,其中N为sizeof(MSG_HEADER)
。我认为您认为它会添加N个字节,但实际上添加了N个MSG_CONFIGURATION
实例。而是使用以下命令:©config.header + 1
也就是说,“获取
copyconfig.header
的地址并转到其后。”您同样可以这样做:
(char*)©config + sizeof(MSG_HEADER)
因为一个
char
的大小是一个字节。或者,由于您的结构已打包:©config.clear_type
因为那是您实际要复制到的第一个字节的地址。
有关更多详细信息,请阅读:Pointer Arithmetic。
关于c - 为什么此结构的内存副本未按预期将字节复制到字节流?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36888633/