C代码缺失函数声明致Rust编译库段错误,该声明作用是什么?
问题:C中未声明函数导致调用Rust库时传入无效指针
问题背景
调试发现,C代码中使用函数和结构体前必须先声明,否则调用Rust函数时会传入无效指针。
Rust库代码(通过cargo build编译)
pub struct Context { arr: Vec<i16>, } #[no_mangle] pub extern "C" fn ctx_gen() -> Box<Context> { Box::new(Context { arr: Vec::new() }) } #[no_mangle] pub extern "C" fn ctx_use(c: *const Context) { let Some(ctx) = (unsafe { c.as_ref() }) else { return }; println!("arr len: {}", ctx.arr.len()); }
C测试代码(通过gcc -o cb test.c ./target/debug/librustapi.a编译)
struct Context; //struct Context *ctx_gen(); void ctx_use(struct Context *ctx); int main(int argc, char *argv[]) { struct Context *ctx = ctx_gen(); ctx_use(ctx); usleep(200 * 1000); }
崩溃现象与调试信息
运行./cb时程序崩溃,gdb调试信息如下:
(gdb) frame 1 #1 0x0000555555566fbf in rustapi::ctx_use (c=0x556422a0) at src/lib.rs:13 13 println!("arr len: {}", ctx.arr.len()); (gdb) p ctx $1 = (*mut rustapi::Context) 0x556422a0 (gdb) p *ctx Cannot access memory at address 0x556422a0
关键补充发现
编译时存在隐式声明警告,打印ctx_gen返回前后的地址发现值被截断:
ctx_gen: 0x5687227d42a0 0x227d42a0
原因解析
取消注释struct Context *ctx_gen();后程序正常运行,核心原因是C语言的隐式函数声明规则:
- 未声明就调用
ctx_gen时,C编译器会默认该函数返回int类型(这是旧C标准的遗留规则,现代编译器会给出警告)。 - Rust的
ctx_gen返回的Box<Context>对应C中的struct Context*,在64位系统中指针是8字节,而int通常是4字节。 - Rust返回8字节指针后,C编译器按4字节
int处理,直接截断高位地址,导致有效地址0x5687227d42a0被截成无效的0x227d42a0,最终触发内存访问崩溃。 - 显式声明
struct Context *ctx_gen();后,C编译器明确知道函数返回8字节指针,会正确处理返回值,避免截断,指针自然有效。
简单总结:隐式声明让C把8字节指针当成4字节int截断,显式声明则告诉C按指针类型处理,解决了地址截断问题。
内容的提问来源于stack exchange,提问作者Catau
相关产品推荐
相关产品推荐

