我有一个项目运行良好,直到发生一些更新(MacOS 和 rustc)。 对用 C 编写的库(从 Rust 调用)的某些调用会导致分段错误:
println!("TEST");
unsafe { some_C_func(); }
输出是“TEST”的四倍,但是 some_C_func 中的 printf 在 println! 之后实际上没有被调用! (Rust) 被调用四次(即使只写入一次)程序因分段错误而中止;就好像 C 函数从未被调用过。
我最好的选择是工具链之间不兼容(尽管这看起来有些牵强)。否则我会认为 Rust 中的未定义行为可能会导致这种情况?
我正在寻找可能导致此类情况发生的问题。
窗口.h:
void* window_window(void*);
窗口.c:
// takes a pointer to a struct defined in this library
void* window_window(void* ptr) {
printf("WINDOW IN C\n");
return ((Window) ptr)->glfwWindow; // return a value of type *GLFWWindow
}
Rust 项目包含一个构建脚本,该脚本可根据给定的 window.h(使用 bindgen)生成 Rust 绑定
所以在 Rust 中映射看起来像这样:
extern "C" {
fn window_window(arg1: *mut ::std::os::raw::c_void) -> *mut ::std::os::raw::c_void;
}
然后从结构体的实现中调用此代码:
struct Window {
ptr: *mut ::std::os::raw::c_void,
}
impl Window {
fn window(&self) -> *mut ::std::os::raw::c_void {
println("WINDOW");
unsafe {
window_window(self.ptr)
}
}
}
输出(调用 Window::window 一次)是
WINDOW
WINDOW
WINDOW
WINDOW
zsh: segmentation fault cargo run
C 库链接到(全静态)GLFW、metal 和 cocoa,亲爱的 Imgui。它们被链接(或者编译到 ImGui 的情况下)到动态库中。
这个问题也出现在一个类似的函数上,该函数返回 int (而不是指针)并被命名为 window_update。
MacOS 塞诺玛 14.5 旧的 Rust 版本我找不到,新版本是最新的:stable-aarch64-apple-darwin (rustc 1.82.0)。
Rust 项目是使用 Cargo 组装的,对于 C,我使用 XCode(用于任何与金属相关的编程)和 CMake。
问题确实是双重定义。 在库中,相同的函数定义了两次(在本例中为 window_window)。
更具体地说,它是在 C 库中定义的,如上所示,但也在 rust 项目中定义,如下所示:
#[no_mangle]
unsafe extern "C" fn window_window(handle: *const ()) -> bool {
println!("THIS IS NOT GOOD");
/* snip */
}
#[no_mangle]
属性使得名称保留在二进制文件中,因此有两个定义。