英文:
First byte is suddenly zeroed while converting to CString
问题
Here is the translated code part you provided:
我想要进行 FFI 调用。为了这样做,我需要将 Rust 字符串转换为以适当编码为零结尾的 C 字符串。我编写了这段代码,但不知何故它会将第一个字节替换为零。为什么会发生这种情况?如何修复这个问题?
使用编码::所有::WINDOWS_1251;
使用编码::{EncoderTrap, Encoding};
使用 std::ffi::{c_char, CString};
fn str_to_c_str(input:&str)- > *const c_char {
让 enc_input:Vec < u8 > = WINDOWS_1251.encode(input,EncoderTrap::Strict).expect("TODO:panic message");
println!("enc_input {:?}", enc_input);
让 cstring:CString = CString::new(enc_input).expect("TODO:panic message");
让 s1 = 不安全 {std::slice::from_raw_parts(cstring.as_ptr(),4)};
println!("str_to_c_str {:?}", s1);
cstring.as_ptr()
}
fn main(){
不安全 {
让 data = str_to_c_str("ABC");
让 s2 = 不安全 {std::slice::from_raw_parts(data,4)};
println!("main {:?}", s2);
}
}
[dependencies]
libc = "0.2.0"
encoding = "0.2"
byteorder = "1.4.3"
如果我像这样重写我的代码,它会有效吗?就像编译器看到在 1
之后没有对 data
的“有效”使用,并且在 CString
中没有自定义释放器,或者没有可见的副作用,编译器是否可以将 data
的释放从 2
移动到 1
作为优化?
使用编码::所有::WINDOWS_1251;
使用编码::{EncoderTrap,Encoding};
使用 std::ffi::{c_char,CString};
不安全 fn ffi_call(arg:*const c_char)- > () {
让 s1 = 不安全 {std::slice::from_raw_parts(arg,4)};
println!("str_to_c_str {:?}", s1);
}
fn str_to_c_str(input:&str)- > CString {
让 enc_input:Vec < u8 > = WINDOWS_1251.encode(input,EncoderTrap::Strict).expect("TODO:panic message");
println!("enc_input {:?}", enc_input);
让 cstring:CString = CString::new(enc_input).expect("TODO:panic message");
cstring
}
fn main(){
让 data = str_to_c_str("ABC");
// 1
不安全 {
ffi_call(data.as_ptr());
}
// 2
}
英文:
I want to do FFI call. To do so i need to convert a Rust string into C-zero-terminated-string in a proper encoding. I wrote this code but somehow it replaces first byte with zero. Why this happen? How do I fix this?
use encoding::all::WINDOWS_1251;
use encoding::{EncoderTrap, Encoding};
use std::ffi::{c_char, CString};
fn str_to_c_str(input: &str) -> *const c_char {
let enc_input: Vec<u8> = WINDOWS_1251.encode(input, EncoderTrap::Strict).expect("TODO: panic message");
println!("enc_input {:?}", enc_input);
let cstring: CString = CString::new(enc_input).expect("TODO: panic message");
let s1 = unsafe { std::slice::from_raw_parts(cstring.as_ptr(), 4) };
println!("str_to_c_str {:?}", s1);
cstring.as_ptr()
}
fn main() {
unsafe {
let data = str_to_c_str("ABC");
let s2 = unsafe { std::slice::from_raw_parts(data, 4) };
println!("main {:?}", s2);
}
}
Here is an actual output:
enc_input [65, 66, 67]
str_to_c_str [65, 66, 67, 0]
main [0, 66, 67, 0]
I expect a last line to be:
main [65, 66, 67, 0]
[dependencies]
libc = "0.2.0"
encoding = "0.2"
byteorder = "1.4.3"
Added
If I rewrite my code like this would it be valid?
Like if a compiler see that there is no "valid" usage of data
after 1
and there is no custom deallocator in CString
or is has no visible side-effect, can the compiler move data
's deallocation from 2
to 1
as an optimisation?
use encoding::all::WINDOWS_1251;
use encoding::{EncoderTrap, Encoding};
use std::ffi::{c_char, CString};
unsafe fn ffi_call(arg: *const c_char) -> () {
let s1 = unsafe { std::slice::from_raw_parts(arg, 4) };
println!("str_to_c_str {:?}", s1);
}
fn str_to_c_str(input: &str) -> CString {
let enc_input: Vec<u8> = WINDOWS_1251.encode(input, EncoderTrap::Strict).expect("TODO: panic message");
println!("enc_input {:?}", enc_input);
let cstring: CString = CString::new(enc_input).expect("TODO: panic message");
cstring
}
fn main() {
let data = str_to_c_str("ABC");
// 1
unsafe {
ffi_call(data.as_ptr());
}
// 2
}
答案1
得分: 1
"不允许,因为这会导致程序出现错误。只要您的代码没有未定义行为,您无需担心编译器优化。如果编译器优化会导致程序出错,那将是编译器的错误(这种情况相当罕见)。”
英文:
> If I rewrite my code like this would it be valid? Like if a compiler see that there is no "valid" usage of data
after 1
and there is no custom deallocator in CString
or is has no visible side-effect, can the compiler move data
's deallocation from 2
to 1
as an optimisation?
No, it is not allowed to, exactly because this will break your program.
As long as you don't have UB in your code, you don't have to worry about compiler optimizations. If they will break your program, it will be a bug in the compiler (and it's pretty rare).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论