c - 在结构中使用 Option<unsafe fn ...> 的奇怪内存布局

标签 c struct rust java-native-interface unsafe

我正在使用来自 here 的 JNI 定义.我创建了一个 JNINativeInterface_,其中大多数成员初始化为 None。然后我运行使用上述结构的 RegisterNatives 字段的 native 代码。我这样初始化了 RegisterNatives 和周围的字段:

SetDoubleArrayRegion: unsafe { transmute(0xdeadbeaf as u64) },
RegisterNatives: Some(register_natives),
UnregisterNatives: unsafe { transmute(0xdeadbeaf as u64) },

register_natives 定义如下(这与库类型完全匹配):

unsafe extern "system" fn register_natives(env: *mut sys::JNIEnv,
                                           clazz: jclass,
                                           methods: *const JNINativeMethod,
                                           nMethods: jint) -> jint {
    unimplemented!()
}

使用 struct segfaults 的 native 代码(并且似乎得到一个 null ptr 而不是 register_natives)。

结构的相关部分在 GDB 下看起来像这样:

0x7ffcf5f4a5b8: 0x0 0x0 0x0 0x0
0x7ffcf5f4a5c8: 0xdeadbeaf  0x0 0x43fd9950  0x55ea
0x7ffcf5f4a5d8: 0xdeadbeaf  0x0 0x0 0x0
0x7ffcf5f4a5e8: 0x0 0x0 0x0 0x0

我很困惑我到底在看什么,因为我期待 0xdeadbeaf ,后跟一个 64 位指针,然后是 0xdeadbeaf,但正如你所看到的,这不是我得到的。我关于选项将如何在幕后表示的假设是否错误?为什么 bindgen/上述库似乎认为 Option 会导致兼容的接口(interface)?

最佳答案

[...] I was expecting 0xdeadbeaf, followed by a 64 bit pointer, followed by 0xdeadbeaf, but as you can see that is not what I get.

我们不能看到相同的东西,因为我确实看到了。

0x7ffcf5f4a5c8: 0xdeadbeaf  0x0 0x43fd9950  0x55ea
0x7ffcf5f4a5d8: 0xdeadbeaf  0x0 0x0 0x0

每个十六进制数都是一个 32 位整数,因此您必须取其中两个来组成一个 64 位整数。第一个是 0x00000000deadbeaf,第二个是 0x000055ea43fd9950(大概是你的 register_natives 函数),第三个也是 0x00000000deadbeaf。 (从地址上也很“明显”:一个64位整数占用8个字节,所以需要两个占用0x10字节。因此,每行有两个64位整数。)

程序段错误的原因可能是因为通过外部代码让 panic 解除是 undefined behavior .尝试将您的 register_natives 函数更改为不会 panic 的函数。

关于c - 在结构中使用 Option<unsafe fn ...> 的奇怪内存布局,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59796437/

相关文章:

c - 删除从文件中读取的重复边缘

arrays - go: struct 中的数组丢失了它的内容

c++ - C 代码中 C++ 代码中的 sizeof 类作为编译时常量

c - 在 FreeBSD 10.2 中读取或写入时从 nullfs 内部获取 inode 编号

c - 为什么在调用计时器的函数中参数具有其他值?

c - 在 switch/case 语句中使用 const struct member

c - 使用基本结构从 void* 中提取值

c - 为什么 Rust 如此优于 C

Rust 声称此模式案例无法访问,为什么?

rust - 为什么在使用 Regex 映射字符串时显然需要 std::borrow::Cow?