gpt4 book ai didi

rust - Rust借用可能未初始化的变量-作为程序员,这对我来说很明显,它将始终被初始化

转载 作者:行者123 更新时间:2023-12-03 11:41:26 25 4
gpt4 key购买 nike

我在这里遇到Rust编译器问题。这段代码最初是用C编写的,我的工作是将其移植到Rust代码中。我没有在这里修改算法或任何东西,但是Rust编译器比C编译器更严格,并且标记了完全有效的代码。

error[E0381]: borrow of possibly-uninitialized variable: `output_file_handler`
--> src/main.rs:318:9
|
318 | output_file_handler.write(b"Why won't it work?");
| ^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `output_file_handler`

error: aborting due to previous error

我正在编写的该程序将MPI库用于Rust,但是现在就忽略它,因为它不是我的问题的一部分。

问题是,我在 File函数的顶部声明了一个可变的 main()对象,该对象在开始时未初始化。现在,因为我正在使用MPI,所以这是一个多进程程序。我正在对此进行一些简化,并删除了不必要的代码来解决我的问题。
my_rank变量基本上保留当前正在执行的进程的“进程ID”,因为同一代码可以由多个进程运行。 my_rank == 0进程仅负责将输出打印到文件, ,其他进程均不执行。在 my_rank == 0的过程中, output_file_handler是“ Activity 的”,而在其他进程中,它保持未初始化状态,因此根本就没有使用过。

除了声明之外, output_file_handler的所有访问和所有访问都在使用 my_rank == 0进行的过程中,因此在使用它时始终会对其进行初始化。但是,编译器太笨了,无法意识到这一点,而且太严格了,因此会惩罚完美的代码!

首先,我有 output_file_handler的声明。然后,我有一些代码启动MPI子系统并“ fork ”一堆进程,并为每个进程分配其各自的等级。然后在 my_rank == 0中初始化 output_file_handler。然后,稍后将执行所有计算密集型任务,包括消息传递,这些任务将为所有进程共享。然后,完成该操作后, output_file_handler应该将这些计算的结果写入文件中。

我无法将这些计算下方的 output_file_handler的初始化移到直接写入输出的位置,因为如果无法打开该输出文件,则根本不应启动这些密集的计算。

从该函数的顶部开始, output_file_handler必须在整个 main()函数中具有作用域,因为如果我在 if my_rank == 0块之一中对其进行定义,则 output_file_handler将超出范围并在 }处被破坏,我想要以后再使用。这就是为什么我必须将 output_file_handler放在全局作用域中的原因,因为我没有其他方法可以从初始化中获取 File对象,因为每个 if { }语句都是自包含的,而从中获取东西的唯一方法是在下一个较低的级别使用更大的范围。而且我认为当 File对象超出范围时,实际文件将关闭。我不希望那样发生。

请原谅我对Rust缺乏知识,但是到目前为止我对这种编程语言的了解还很少,我的工作是将该应用程序从C移植到Rust。不,除了MPI,我不能将其他任何库用于多线程/多处理。
fn main() {
// Because the mpirun executable itself generates standard error and standard output,
// I need to create a new File where the application's output should be written.
let mut output_file_handler : File;
// Similarly, this is the File where the application's timing information shoudl be written.
let mut timing_file_handler : File;

let universe = mpi::initialize().unwrap();
let world = universe.world();

let comm_size : i32 = world.size();
let my_rank : i32 = world.rank();

/* Some more code here... */

// Open up the output file.
let output_filename : String = "output".to_string();

// The create() static method opens a file in write-only mode.
// If the file already existed, the old content is destroyed. Otherwise, a new file is created.
let create_file_handler = File::create(&output_filename);
// If File::create() succeeds, it returns an instance of Ok() that contains a file handler.
// If File::create() fails, it returns an instance of Err() that contains more information about the kind of error that happened.
output_file_handler = match create_file_handler {
Ok(file) => {
let dummy : i8 = 5;
// Send the success message to all processes.
for i in 0..comm_size {
world.process_at_rank(i).send_with_tag::<i8>(&dummy, 100);
}

file // quantity without a ; at the end, is returned by the match statement
},

Err(error) => {
eprintln!("ERROR: Could not open the file {} for writing output.", output_filename);
process::abort();
}
};
// Make the other ranks either wait for a success message to be sent, or be killed upon failure.
// This is used as a synchronization device.
} else {
// recieve_with_tag::<i8>() returns a tuple `(i8, mpi::point_to_point::Status)`
// recieve_with_tag::<i8>() takes the tag as a parameter.
let __dummy = (world.process_at_rank(0).receive_with_tag::<i8>(100)).0;
}


/* After that is done, there is a lot of very intensive computations performed here.
This code is shared by all the processes. */

// Later, the final output is written to the file.
if my_rank == 0 {
output_file_handler.write(b"Why won't it work?");
}

}

最佳答案

在您的程序中有一个条件子句,其中有条件设置output_file_handler而没有设置。让我们从一个简化的示例开始:

fn main() {
let mut output_file_handler: File;

if true {
let output_filename: String = "output".to_string();

let create_file_handler = File::create(&output_filename);
output_file_handler = match create_file_handler {
Ok(file) => file,

Err(error) => {
println!(
"ERROR: Could not open the file {} for writing output.",
output_filename
);
process::abort();
}
};
} else {
// output_file_handler is not set
}

output_file_handler.write(b"Why won't it work?");
}

使用简单的 Option<File>将使它看起来像:
fn main() {
let mut output_file_handler: Option<File>;

if true {
let output_filename: String = "output".to_string();

let create_file_handler = File::create(&output_filename);
output_file_handler = match create_file_handler {
Ok(file) => Some(file),

Err(error) => {
println!(
"ERROR: Could not open the file {} for writing output.",
output_filename
);
process::abort();
}
};
} else {
output_file_handler = None;
}

output_file_handler.unwrap().write(b"Why won't it work?");
}

如果您可以确保else块以防止以后再使用 output_file_handler的方式设置所有变量,那么即使没有 Option,也可能有更复杂的解决方案。

关于rust - Rust借用可能未初始化的变量-作为程序员,这对我来说很明显,它将始终被初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59435327/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com