winapi - 为什么从 winapi 复制到我的代码中的结构定义没有相同的行为?
问题描述
我正在尝试使用crate中该结构的定义IMAGE_DOS_HEADER
来读取模块的。winapi
这是我的工作代码:
let mut IDH: IMAGE_DOS_HEADER = uninitialized();
copy_nonoverlapping(library, (&mut IDH as *mut IMAGE_DOS_HEADER) as *mut c_void, size_of::<IMAGE_DOS_HEADER>());
我意识到它winapi
太大了,我希望我的二进制文件小于 1 兆字节,所以我IMAGE_DOS_HEADER
自己声明了结构:
#[derive(Copy, Clone)]
pub struct _IMAGE_DOS_HEADER{
pub e_magic: u16,
pub e_cblp: u16,
pub e_cp: u16,
pub e_crlc: u16,
pub e_cparhdr: u16,
pub e_minalloc: u16,
pub e_maxalloc: u16,
pub e_ss: u16,
pub e_sp: u16,
pub e_csum: u16,
pub e_ip: u16,
pub e_cs: u16,
pub e_lfarlc: u16,
pub e_ovno: u16,
pub e_res: [u16; 4],
pub e_oemid: u16,
pub e_oeminfo: u16,
pub e_res2: [u16; 10],
pub e_lfanew: i32,
}
当我这样做时,结构的所有字段都会得到奇怪的值(例如:)e_magic = 0x3
。
我决定在这两种情况下都将结构转换为数组,即使它们在编程上完全相同。
println!("{:?}", std::mem::transmute::<IMAGE_DOS_HEADER, [u8;0x40]>(IDH).to_vec());
对于他们俩,它都打印了:
[77, 90, 144, 0, 3, 0, 0, 0, 4, 0, 0, 0, 255, 255, 0, 0, 184, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 0, 0, 0]
这真的很奇怪。他们的字段值之间不应该有任何差异。然后我复制打印的数组并将其转换为我的结构,看看是否所有字段都正常。
let dos: [u8;0x40] = [77, 90, 144, 0, 3, 0, 0, 0, 4, 0, 0, 0, 255, 255, 0, 0, 184, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 0, 0, 0];
println!("{}", std::mem::transmute::<[u8;0x40], _IMAGE_DOS_HEADER>(dos).e_magic);
第一个字段等于3
。我有两个结构,具有相同的字段和完全相同的大小(我已验证),我采用一个数组,将其转换为这些结构,然后得到不同的字段。
如您所见3
,数组转储中有一个,但它不应该与结构的第一个字段(e_magic
)相关联,这没有意义,为什么它会与另一个字段一起使用?
我想我在初始化结构时遗漏了一些东西,但是什么?
解决方案
您没有复制相同的定义,而是复制了文档中显示的部分。这是(截断的)实际定义:
STRUCT!{struct IMAGE_DOS_HEADER {
e_magic: WORD,
e_cblp: WORD,
// ...
e_res2: [WORD; 10],
e_lfanew: LONG,
}}
值得注意的是,这使用了STRUCT
宏,它定义了一些特征,但更重要的是将类型标记为repr(C)
:
#[repr(C)] #[derive(Copy)] $(#[$attrs])*
pub struct $name {
$(pub $field: $ftype,)+
}
没有指定 Rust 结构的布局,因此与 C 结构相比,您的结构有一些其他的排序和填充,并且不会工作。
我意识到winapi太大了,我希望我的二进制文件小于一兆,所以我自己声明了IMAGE_DOS_HEADER结构
这是不正确的推理。未使用的库中的代码将从最终的二进制文件中删除。
也可以看看:
推荐阅读
- arrays - 为什么我不能通过数组映射
- c# - 与 Azure SQL (ALLOW_ROW_LOCKS) 相比,使用 EF Core 生成的 PK 在本地 SQL Server 上有所不同
- c - 具有随机数的数组仅包含相同的值?
- php - 使用 PHP 和 curl 抓取一些网站时遇到问题
- sparql - 城市、国家和国家属性的简单 Wikidata SPARQL 查询超时
- php - Laravel 在创建具有两个时间戳列的表时出错
- php - 从 cURL 获取 CURLOPT_HTTPHEADER 的值
- react-native - setState 没有改变初始状态
- c - fwrite 和 fread 动态分配的 char 数组,其中包含数字和符号,仅读取 4 个字节而不是 9 个
- solr - 带有日期的 Solr 相关数据搜索