Skip to content

Rust FFI诊断:从符号到生命周期 ​

示例未执行,以下是诊断方法和读者未来自查步骤,不是已运行工具日志。先按构建、链接、加载、调用、销毁阶段定位;不要用修改指针或强制类型转换试探崩溃。

找不到导出符号 ​

Rust FFI的undefined reference诊断先核对导出符号和库类型:Rust需要C ABI与固定符号名,C声明需和头文件一致,链接器还必须实际读取正确库。找到文件不等于找到符号;拼写、目标架构和MSVC导入库都会影响结果。先核查Cargo产物目录和CMake的RUST_TARGET_DIR,再由读者使用目标平台符号工具查看导出,不能随意添加no_mangle掩盖签名错误。

C++宿主漏写extern C可能导致名称修饰;本例头文件已经包含保护。静态链接的依赖和库顺序问题与DLL加载失败不同,追加运行PATH无法修复链接阶段undefined reference。即便同名符号成功链接,错误参数类型也可能在调用时破坏状态。

DLL和共享库加载失败 ​

Rust FFI的动态库加载失败诊断区分链接期导入库和运行期动态库:Windows需要DLL位于受控搜索位置,Unix需要正确的RPATH或加载路径。当前CMake只提供构建目录可用的部署安排,复制exe而遗漏库会失败。先核对实际产物、位数和依赖库,再检查加载路径;不要将陌生下载目录永久加入全局PATH。

macOS的动态库安装名、Linux的依赖搜索和Windows的DLL搜索机制并不相同。交叉构建还需相应C工具链与目标系统库,本机C编译器不能自动链接其他架构的Rust产物。staticlib也不能通过重命名变成动态库。

非法UTF8与崩溃区别 ​

Rust FFI的非法UTF8诊断只适用于有效可读缓冲区,字节0xff会返回UTF8错误码;悬垂指针、错误长度或错误句柄可能在编码校验之前已触发UB。null判断不验证可读性,from_raw_parts也不探测分配边界。遇到崩溃应追踪分配、长度来源、借用期间写入和释放顺序,不能把catch_unwind当访问违规处理器。

本例接受null与零长度并绕开原始切片创建;若把代码改为对null直接from_raw_parts,空输入也违反函数前提。地址合法但长度超isize上界会返回ARGUMENT;地址可读却长度谎报仍是宿主责任。不要用随机指针生成测试声称验证了安全性。

回调后崩溃与重复释放 ​

Rust FFI的回调后崩溃诊断应核对context寿命、标签借用和释放次数;同步回调只保证调用返回前借用,保存标签地址仍可能悬垂。若回调销毁同一句柄或重入同一句柄,就违反独占协议;如果外部线程并发free,也无法靠函数内null判断保护。应从所有指针副本和库卸载顺序还原事件。

本例Host在main栈中直到返回,且没有异步工作;若修改为保存context,就必须同时增加停止、等待在途回调和注销协议。使用调试器或内存检测工具应由读者另行运行,静态阅读无法确认实际调度和内存安全。

panic错误与验证边界 ​

Rust FFI的PANIC错误诊断要求停止复用句柄并检查panic配置,因为catch_unwind只覆盖unwind路径,不覆盖abort或外国异常。看到panic hook输出并不自动说明展开已穿过C;需要结合返回码和终止行为判断。PANIC不承诺回滚,正常ARGUMENT/UTF8/OVERFLOW才有不修改状态的契约。

本包只运行Markdown、Vue模板和TOML/JSON纯解析,未运行Rust工具、C编译、CMake、宿主或内存检测器。没有编译产物、运行日志、性能和跨平台兼容证据。static-results记录同源覆盖与源码hash,template-results只证明当前文档模板可编译,不可推导ABI或实际二进制正确。

练习:给诊断排序 ​

Windows宿主在链接成功后提示找不到DLL,开发者想改Rust函数的参数类型。列出先检查的三项,并解释改签名为何无助于当前阶段。

参考解答

先检查宿主旁是否存在对应DLL、DLL与exe是否同架构、DLL依赖是否可加载。参数类型影响调用阶段,无法使加载器找到文件;修改签名还可能破坏已经匹配的头文件。先修部署,再核对返回码和回调预期,每个阶段保留自己的证据。

官方依据 ​

Nomicon FFI、切片原始指针前提、panic捕获限制。涉及平台加载器时应结合所用系统的原始文档继续核查,本文没有冒称实测部署。

继续阅读