You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 22:35:20