下面的C代码的RUST等效是什么?



我有一个小的C代码,通过修改堆栈地址上的数据来演示运行时堆栈功能。

#include <stdio.h>
int * fun() {
int a = 10;
return &a;
}
int * fun2() {
int b = 20;
return &b;
}
int main () {
int *a = fun();
int *b = fun2();
printf("a:%d b:%dn", *a, *b);
return 0;
}

输出如下:20 b: 20这表明'fun2'中的'b'与'fun'中的'a'使用了相同的堆栈地址。

我也想在Rust中测试一下。最简单的方法是什么?

我尝试借用,但编译器说"没有值可以借用"。

如果您希望具有与C中相同的未定义行为,您可以这样做(幸运的是,这需要unsafe):

fn fun() -> *const i32 {
let a = 10;
&a
}
fn fun2() -> *const i32 {
let b = 20;
&b
}
fn main() {
let a = fun();
let b = fun2();
// SAFETY: Don't do this. This is pure Undefined Behavior.
unsafe {
println!("a: {} b: {}", *a, *b);
}
}

这是与C版本完全相同的UB。在调试模式下,在操场上打印a: 21885 b: 21885,在释放模式下打印a: -482758656 b: 32767。你的会不一样。

如果您也想要与C版本相同的结果,您可以使用printf()。小心你使用的代码,更改可能会导致它不再"工作"。因为它将使用不同的堆栈布局。当然,这是非常脆弱的:

use std::ffi::c_char;
fn fun() -> *const i32 {
let a = 10;
&a
}
fn fun2() -> *const i32 {
let a = 20;
&a
}
extern "C" {
fn printf(format: *const c_char, ...);
}
fn main() {
let a = fun();
let b = fun2();
unsafe {
printf(b"a: %d b: %dn" as *const u8 as *const c_char, *a, *b);
}
}

它在调试模式下打印a: 20 b: 20,在发布模式下打印a: 1 b: 1(你的可能不同)。

下面的C代码的RUST等效是什么?

目标是可疑的,因为C代码是坏的。


int *a = fun();未定义行为(UB),因为代码试图保存一个无效的指针。复制无效指针是非法的。后来在printf("a:%d b:%dn", *a, *b);中尝试引用的*a也是UB。

int * fun() {
int a = 10;
return &a; // &a invalid when function completes.
}

ab具有自动存储,并在函数返回时销毁。一旦函数返回,它的堆栈帧被弹出(销毁)。根据C11标准的以下子句,返回(并使用)局部变量的地址调用未定义行为:

6.2.4对象的存储持续时间:

2对象的生命周期是程序在此期间执行的部分保证为它保留哪个存储。一个物体存在,有一个常量地址,并始终保留其最后存储的值它的生命周期。如果对象在其生命周期之外被引用,则行为是未定义的。指针的值变得不确定

字面意思相同:

#![no_main]
extern {
fn printf(format: *const u8, ...); // u8 or i8 doesn't matter in this case
}
#[no_mangle]
extern fn fun() -> *const i32 {
let a = 10;
&a
}
#[no_mangle]
extern fn fun2() -> *const i32 {
let a = 20;
&a
}
#[no_mangle]
unsafe extern main() -> i32 {
let a = fun();
let b = fun2();
printf("a:%d b:%dn".as_ptr(), *a, *b);
0
}

最新更新