[英]Cannot properly memcpy a char array to struct
所以我有一個名為packet的結構
struct Packet {
unsigned int packet_type;
wchar_t packet_length[128];
wchar_t file_name[256];
wchar_t template_name[256];
wchar_t file_name_list[1024];
wchar_t file_data[1024];
void serialize(char * dat) {
memcpy(dat, this, sizeof(Packet));
}
void deserialize(const char * dat) {
memcpy(this, dat, sizeof(Packet));
}
};
我正試圖從這些數據中剔除
{byte[2692]}
[0] 0 unsigned int packet_type; (4 bytes)
[1] 0
[2] 0
[3] 0
[4] 50 '2' wchar_t packet_length[128]; (128 bytes)
[3] 0
[5] 54 '6'
[3] 0
[6] 57 '9'
[3] 0
[7] 50 '2'
[8] 0
[...] 0
[132] 112 'p' wchar_t file_name[256]; (256 bytes)
[133] 0
[134] 104 'h'
[...] 0
但deserialze中的memcpy並沒有給我file_name,但它確實給了我packet_length。 怎么了? 謝謝!
編輯:所以我現在很清楚wchar_t占用的空間比我想象的要多; 但是,我被告知不要使用memcpy?
我已經編寫了這個反序列化方法,它正確地抓取了數據。 這會導致安全漏洞嗎?
void deserialize(const char * dat) {
memcpy(&(packet_type), dat, 4);
memcpy(&(packet_length[0]), dat + 4, 128);
memcpy(&(file_name[0]), dat + 132, 256);
memcpy(&(template_name[0]), dat + 388, 256);
memcpy(&(file_name_list[0]), dat + 644, 1024);
memcpy(&(file_data[0]), dat + 1668, 1024);
}
請不要使用此方法來序列化結構。 這完全不便攜。
此外,編譯器還可以根據目標體系結構,字節序,優化和一堆其他內容來填充,對齊或重新排序成員。
更優雅的方法是使用boost :: Serialization ,它以便攜方式處理低級細節。
另一方面,如果你只是想檢查你的結構,那么調試器就派上用場了......
char
數組的布局假定wchar_t
的大小是兩個字節; 它不是 - 這里是wchar_t
的大小為4
的系統的示例,因此Packet
的大小是10756
,而不是2692
字節:( 鏈接到演示 )。
這就是為什么編輯中的memcpy
技巧會出現問題:它假設char[]
數組中的數據布局與wchar_t[]
數組的布局相匹配,它可能匹配也可能不匹配。 如果您知道數據數組具有以小端格式存儲的雙字符元素(LSB優先),您可以編寫自己的函數將數據從源轉換為目標,並調用它以獲取部分序列化數據,如這個:
void bytes_to_wchar(wchar_t *dest, const unsigned char* src, size_t length) {
for (size_t i = 0 ; i != lengt ; i++) {
dest[i] = src[2*i] | (src[2*i+1] << 8);
}
}
現在,您可以使用此函數將數據復制到wchar_t
數組中,而與目標系統上的wchar_t
大小或目標系統的字節順序無關:
void deserialize(const char * dat) {
bytes_to_wchar(packet_type, dat + 0, 4);
bytes_to_wchar(packet_length[0], dat + 4, 128);
bytes_to_wchar(file_name[0], dat + 132, 256);
bytes_to_wchar(template_name[0], dat + 388, 256);
bytes_to_wchar(file_name_list[0], dat + 644, 1024);
bytes_to_wchar(file_data[0], dat + 1668, 1024);
}
當您使用相同的編譯器在同一硬件上執行此操作時,從內存中保存數據並將其寫回的快捷方式可能會起作用。 即使這樣,它仍然對您使用的標頭和編譯器設置中的小調整很敏感。
如果需要復制到struct
的字符數組具有固定布局,則需要編寫一個函數來處理該布局,將兩字節組轉換為wchar_t
,將四字節組轉換為unsigned int
,依此類推。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.