
windows wsl DISTRIB_ID=Ubuntu DISTRIB_RELEASE=20.04 DISTRIB_CODENAME=focal DISTRIB_DESCRIPTION="Ubuntu 20.04.6 LTS arch x86_64 rust version stable-x86_64-unknown-linux-gnu (default) rustc 1.83.0 (90b35a623 2024-11-26) Cargo.toml
[package] name = "demo" version = "0.1.0" edition = "2021" [dependencies] reqwest = {version = "0.11",default-features = false,features = ["rustls-tls"]} tokio = {version = "1.42",features = ["full"]} #[tokio::main] async fn main() { let mut tasks=vec![]; for _i in 0..2{ let t=tokio::spawn(async move { let result=reqwest::get("https://github.com").await; if let Ok(result) = result { println!("{:?}",result.status()); } }); tasks.push(t); } for t in tasks { t.await.expect("Something went wrong"); } } ```bash root@computer1:/demo/# RUSTFLAGS="-Ctarget-feature=+crt-static" cargo run --target x86_64-unknown-linux-gnu root@computer1:/demo/# Segmentation fault 在开启静态链接情况下,该代码会导致段错误。具体导致的原因 hyper#2537
主要是因为"github.com:443".to_socket_addrs(); 并发会导致段错误。
main.rs 这个代码也可以出发这个段错误
use std::net::ToSocketAddrs; #[tokio::main] async fn main() { let mut tasks=vec![]; for _i in 0..2{ let t=tokio::spawn(async move { // let result=reqwest::get("https://github.com").await; // if let Ok(result) = result { // println!("{:?}",result.status()); // } "github.com:443".to_socket_addrs(); }); tasks.push(t); } for t in tasks { t.await.expect("Something went wrong"); } } 更底层的原因是,这位老哥的说的getaddrinfo
这意味着你要静态链接,http 或者其他什么涉及到主机名转换并发调用了 getaddrinfo 就会大概率会出现段错误,进程就会直接没了。rust 的静态链接和交叉编译,太菜鸡了。 如果你不使用静态链接,而使用动态链接,那么你最好保证你的开发机器软件包版本和你生产环境的软件版本保持一致,不然动态链接 openssl ,在生成看起来已经安装了 openssl ,但是提示找不到。静态链接这一点,golang践踏 rust
1 aloxaf 355 天前 issue 里和 stackoverflow 里不都说了么,glibc 压根不支持静态链接,尤其是 gethostbyname 。 想静态链接就用 musl ,ssl 切换到 rustls 。 |
2 dilfish 355 天前 via Android 这个问题我遇到过,你想静态编译 redis 也会警告。 go 是自己写了一套,rust 也有对应的库, |
3 wolfsun 355 天前 同意楼上,楼主非要踩一捧一,在智商这一点,狗践踏楼主 |
4 virusdefender 355 天前 glibc 根本不能静态链接,有些里面的函数你用到的时候还会动态寻找其他的 so ,比如一些密码类的 |
5 hingle 355 天前 OP 就是专门踩 rust 捧 go 的。https://v2ex.com/t/1090526 |
6 bli22ard OP @aloxaf 我测试了一下,musl 静态链接这个代码确实没有问题。linux 静态链接还是得 musl 。 @dilfish 下次可以试试 musl 静态链接 @virusdefender 看来 glibc 确实是不能静态链接。即使静态链接编译成功也是假象,段错误在运行时等着。 |
9 adoal 355 天前 glibc 大毒瘤 |
10 dogfeet 355 天前 我都是: 不使用 native-tls ,专用 rustls 使用 cargo zigbuild ,还可以指定 glibc 版本,挺无脑的,没你说的那么费劲。 |
11 dogfeet 355 天前 对了,刚忘说了,我是直接在 windows 上交叉编译 linux 的。安装下 ziglang 和 zigbuild 就行了。 没觉得比 Golang 麻烦在哪里。 |
12 kagenomirai OP 说的也不算事实。链接不是 rust 的责任。你换了 C C++ 或者 D 你都得链接一个 libc ,除非你不调系统的 api 或者有一层 vm 的包装。而 glibc 众所周知是不可以静态链接的。rust 这类系统级编程语言是不可能脱离 c 的 api ,顶多帮你做一些 dirty work ,到头来免不了做系统层面上的兼容。所有 OP 拿 go 和 rust 比就好像拿 lua 和 c 比一样,都不是同一个类语言,在设计上解决的问题也不同。 归根结底,比较两个(针对某一问题设计的)语言根本没有意义。比较锤子和螺丝刀有意义吗? |
13 bli22ard OP @adoal 感觉有点道理 @dogfeet cargo zigbuild 没试过,我是用 https://github.com/cross-rs/cross 交叉编译。zigbuild 不静态链接,到运行的机器容易提示找不到对应 so 吧?静态链接,最佳实战应该就是 musl 了。 @kagenomirai glibc 众所周知是不可以静态链接的,这个我见识短,之前不知道。 和 lua 比不合适,lua 需要依赖解释器。rust 和 golang 编译输出都是可执行程序,所以它们比较有可比性。编译和链接这块 golang 难道不比 rust 方便? go buid 指定 os 和 arch ,就可以了。 |
14 dogfeet 355 天前 @bli22ard 是的,想要不依赖 glibc 就用 musl ,想要不依赖 openssl ,就是用 rustls 。 至于要方便的交叉编译,直接使用 cargo zigbuild 就行。 大致就是这么简单。 |
15 dogfeet 355 天前 @dogfeet 我一般还是用 glibc ,但是不用 native-tls(openssl)。虽然很多人说 musl 性能较 musl 差,但其实我并不在乎这个,只是没觉得 glibc 问题有那么严重。毕竟这玩意和内核关系紧密,不像 openssl 。 在加上 zigbuild 能很方便的指定 glibc 的版本,没觉得这个有啥麻烦的地方。所以继续 glibc |
16 bli22ard OP @dogfeet zigbuild 我试了下,使用 rustls , 指定低版本的 glibc ,比如 2.22 ,那大多数服务器都可以兼容,不知道这样做有没有什么坏处 |
17 capric 354 天前 建议用 https://github.com/rust-cross/cargo-zigbuild 或者 https://github.com/cross-rs/cross 静态链接 musl ,不要静态链接 glibc ,可以动态链接 2012 年的 glibc2.17 ,就可以在主流相同指令集的 linux 上跑起来,比如 cargo zigbuild --target aarch64-unknown-linux-gnu.2.17 |
18 bli22ard OP > 建议用 https://github.com/rust-cross/cargo-zigbuild 或者 https://github.com/cross-rs/cross 静态链接 musl ,不要静> 态链接 glibc ,可以动态链接 2012 年的 glibc2.17 ,就可以在主流相同指令集的 linux 上跑起来,比如 cargo zigbuild > --target aarch64-unknown-linux-gnu.2.17 @capric rust 编译最佳实战 |