马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
1. Rust简介
Rust 是一种今世化的编程语言,专注于性能和内存安全。它由 Mozilla 基金会于 2015 年正式发布,旨在提供 C/C++ 风格的体系级编程本事,同时制止传统编程语言中常见的内存管理标题。Rust 接纳了独特的全部权体系(ownership system),通过编译器在编译时检测代码中的潜伏内存标题,从而制止了诸如空指针解引用、内存走漏和数据竞争等常见错误。
2. Rust 相比 C 可以大概带来什么利益
2.1 内存安全与制止内存走漏、踩内存
在 C 语言中,内存管理通常依赖步伐员手动调用 malloc、free 等函数。假如步伐员在某些环境下忘记开释内存,就会导致内存走漏;假如误操纵了指针,大概会导致内存被访问后瓦解或产生未界说举动。Rust 则通过全部权机制(Ownership)和借用(Borrowing)机制来办理这些标题,确保内存在利用完后自动开释,且不会发生数据竞争或访问无效内存。
Demo:全部权转移示例- fn fun1() -> String {
- let s1 = String::from("Hello");
- println!("In fun1: {}", s1);
- fun2(s1) // Ownership transferred to fun2
- }
- fn fun2(s2: String) -> String {
- println!("In fun2: {}", s2);
- fun3(s2) // Ownership transferred to fun3
- }
- fn fun3(s3: String) -> String {
- println!("In fun3: {}", s3);
- fun4(s3) // Ownership transferred to fun4
- }
- fn fun4(s4: String) -> String {
- println!("In fun4: {}", s4);
- fun5(s4) // Ownership transferred to fun5
- }
- fn fun5(s5: String) -> String {
- println!("In fun5: {}", s5);
- s5 // Ownership stays with fun5 until it goes out of scope
- }
- fn main() {
- let result = fun1(); // Calling fun1 will start the ownership transfer chain
- println!("Returned from fun5: {}", result); // Ownership remains with result here
- }
复制代码 表明: 在上面的代码中,我们通过函数调用链转达 String 范例的值,每次调用都会转移全部权。Rust 会自动在 String 超出作用域时开释内存,制止了内存走漏和踩内存的标题。
2.2 Rust 与 C 的内存安全上风
- 自动内存管理: Rust 利用全部权和生命周期来确保内存的自动开释。你无需担心手动管理内存或引入内存走漏。可以简单的这么以为,在linux平台上,利用rust编写的步伐,根本上就不消依赖asan、valgrind来检测内存走漏了。
- 编译时查抄: Rust 的编译器会在编译期间查抄全部权和借用规则,提前发现并陈诉错误。
3. Rust 怎样调用 C 库
Rust 提供了 unsafe 关键字,答应直接调用 C 语言编写的函数。这种方式能让 Rust 与 C 语言举行高效的交互,但步伐员须要自己包管 C 函数的精确性和安全性。
Demo:Rust 调用 C 函数
假设我们有一个 C 库,此中包罗一个简单的加法函数:- // add.c
- #include <stdio.h>
- int add(int a, int b) {
- return a + b;
- }
复制代码 然后,利用 Rust 来调用这个 C 函数:- extern "C" {
- fn add(a: i32, b: i32) -> i32;
- }
- fn main() {
- unsafe {
- let result = add(5, 10);
- println!("The sum is: {}", result);
- }
- }
复制代码 表明: extern “C” 用来声明 C 函数,Rust 会通过 FFI(外部函数接口)与 C 代码举行交互。留意,unsafe 块须要显式标记,由于我们在调用 C 代码时须要绕过 Rust 的安全查抄。
4. C 怎样调用 Rust 库
同样,Rust 也可以编译成 C 可以调用的共享库。假设我们有一个 Rust 库 mylib,此中包罗一个简单的加法函数。
Demo:C 调用 Rust 函数
起首,编写一个 Rust 库:- // lib.rs
- #[no_mangle]
- pub extern "C" fn add(a: i32, b: i32) -> i32 {
- a + b
- }
复制代码 然后,编译该 Rust 代码为一个 C 可调用的共享库。Rust 编译器会天生一个 .so 或 .dll 文件,详细取决于你的操纵体系。
在 C 中调用 Rust 函数:- // main.c
- #include <stdio.h>
- extern int add(int a, int b);
- int main() {
- int result = add(5, 10);
- printf("The sum is: %d\n", result);
- return 0;
- }
复制代码 表明: 通过利用 extern 声明 Rust 函数,C 语言就可以调用 Rust 编写的函数了。#[no_mangle] 属性确保 Rust 编译器不改变函数名称,保持 C 调用时的名称同等。
5. Rust 不能完全制止逻辑错误
固然 Rust 提供了强大的内存安全保障,但它并不能完全制止 逻辑错误。逻辑错误通常发生在步伐的计划和实现阶段,须要步伐员自己举行公道的错误查抄和处理处罚。
Demo:访问不存在的 JSON 键- use serde_json::Value;
- fn main() {
- let data = r#"{ "key1": "value" }"#;
- let json: Value = serde_json::from_str(data).unwrap();
- // 这里直接访问不存在的 "key2",会导致 panic
- let value = json["key2"].as_str().expect("key2 not found!");
- println!("key2: {}", value);
- }
复制代码 表明: 在这个例子中,访问一个不存在的键 key2 会导致 unwrap() 或 expect() 触发 panic。这是由于 Rust 并不陵暴逻辑层面查抄全部条件,步伐员必须自己处理处罚 Option 和 Result 范例的返回值,防止这种运行时错误。
总结
- Rust 相比 C 的上风: Rust 提供了强大的内存安全机制,通过全部权和生命周期查抄来制止内存走漏、踩内存等标题。与 C 差别,Rust 通过编译时查抄明显镌汰了内存错误。
- 跨语言调用: Rust 可以调用 C 函数,C 也可以调用 Rust 编写的库,这为 Rust 与其他语言的集成提供了机动性。
- 逻辑错误: 只管 Rust 在内存管理和并发方面提供了极大的保障,但它不能完全消除步伐员的逻辑错误,开发者仍需审慎处理处罚业务逻辑。
|