以下代码产生一个警告,但我预计会产生两个警告;我每次写一个CString::new("A CString").unwrap().as_ptr():
use std::ffi::CString;
use std::os::raw::c_char;
extern "C" {
fn puts(s: *const c_char);
}
macro_rules! mymacro {
() => {
puts(CString::new("A CString").unwrap().as_ptr());
};
}
fn main() {
unsafe {
puts(CString::new("A CString").unwrap().as_ptr());
mymacro!();
}
}
Run Code Online (Sandbox Code Playgroud)
warning: getting the inner pointer of a temporary `CString`
--> src/main.rs:16:49
|
16 | puts(CString::new("A CString").unwrap().as_ptr());
| ---------------------------------- ^^^^^^ this pointer will be invalid
| |
| this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
|
= note: `#[warn(temporary_cstring_as_ptr)]` on by default
= note: pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned
= help: for more information, see https://doc.rust-lang.org/reference/destructors.html
Run Code Online (Sandbox Code Playgroud)
它确实对代码进行了两次评估:
A CString
A CString
Run Code Online (Sandbox Code Playgroud)
我有什么误解吗?
当我展开宏时,很明显我有两行应该发出警告。
我正在使用 rustc 1.58.1 (db9d1b20b 2022-01-20)
注释掉这两行似乎 Rust 目前确实没有对宏调用发出警告。
我认为这是因为一般来说不可能对不安全代码中的所有此类情况发出警告,因此在一定程度上,一个微小的更改将影响实现是否检测到危险代码并发出警告。
在这种情况下,时间范围确实很短,这可能表明该区域的优先级相对较低,因此比 Rust 实现的其他区域受到的关注较少。
您还可能认为宏调用应该是“内联的”,因此实现应该看到相同的代码,但显然情况并非如此。卫生的实现可能要求实现记住宏定义的词法范围以及生成的代码。