- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
描述
我试图在我的 Windows 机器上生成线程 #[no_std]
crate ,但我在 __chkstk 中遇到问题功能。首先,我使用 std 创建了一个 crate,并尝试在 libstd 中找到负责生成线程的位置。
Libstd 代码(缩短为仅显示相关部分)
// libstd/thread/mod.rs
pub fn spawn<F, T>(f: F) -> JoinHandle<T>
where
F: FnOnce() -> T,
F: Send + 'static,
T: Send + 'static,
{
Builder::new().spawn(f).expect("failed to spawn thread")
}
// libstd/thread/mod.rs
impl Builder {
pub fn spawn<F, T>(self, f: F) -> io::Result<JoinHandle<T>>
where
F: FnOnce() -> T,
F: Send + 'static,
T: Send + 'static,
{
unsafe { self.spawn_unchecked(f) }
}
pub unsafe fn spawn_unchecked<'a, F, T>(self, f: F) -> io::Result<JoinHandle<T>>
where
F: FnOnce() -> T,
F: Send + 'a,
T: Send + 'a,
{
// ...
imp::Thread::new(
mem::transmute::<Box<dyn FnOnce() + 'a>, Box<dyn FnOnce() + 'static>>(Box::new(
main,
)),
)
// ...
}
}
// libstd/sys/windows/thread.rs
impl Thread {
pub unsafe fn new(p: Box<dyn FnOnce()>) -> io::Result<Thread> {
extern "system" fn thread_start(main: *mut c_void) -> c::DWORD {
unsafe { start_thread(main as *mut u8); }
0
}
let p = box p;
let ret = c::CreateThread(
// ...
thread_start,
&*p as *const _ as *mut _,
// ...
);
if ret as usize == 0 {
Err(io::Error::last_os_error())
} else {
mem::forget(p);
Ok(Thread { handle: Handle::new(ret) })
};
}
}
// libstd/sys_common/thread.rs
pub unsafe fn start_thread(main: *mut u8) {
// ...
Box::from_raw(main as *mut Box<dyn FnOnce()>)()
}
// libstd/sys/windows/c.rs
extern "system" {
// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createthread
pub fn CreateThread(
lpThreadAttributes: LPSECURITY_ATTRIBUTES,
dwStackSize: SIZE_T,
lpStartAddress: extern "system" fn(*mut c_void) -> DWORD,
lpParameter: LPVOID,
dwCreationFlags: DWORD,
lpThreadId: LPDWORD,
) -> HANDLE;
}
#[repr(C)]
struct Handle(usize);
fn spawn_std_like<F, T>(f: F) -> Handle
where
F: FnOnce() -> T,
F: Send + 'static,
T: Send + 'static,
{
try_spawn_std_like(f).expect("failed to spawn thread")
}
fn try_spawn_std_like<F, T>(f: F) -> Result<Handle, ()>
where
F: FnOnce() -> T,
F: Send + 'static,
T: Send + 'static,
{
extern "system" fn thread_start(main: *mut u8) -> u32 {
unsafe { Box::from_raw(main as *mut Box<dyn FnOnce()>)(); }
0
}
let p = Box::new(Box::new(f));
let handle = CreateThread(
thread_start,
&*p as *const _ as *mut _
);
if handle.0 != 0 {
core::mem::forget(p);
Ok(handle)
} else {
Err(())
}
}
// Minimal version of `kernel32.CreateThread`, with only the relevant parameters.
#[allow(non_snake_case)]
extern "system" fn CreateThread(
start_address: extern "system" fn(*mut u8) -> u32,
parameter: *mut u8
) -> Handle {
start_address(parameter);
// Emulate successful `CreateThread` call.
Handle(4)
}
spawn_std_like(|| println!("std_like!"));
调用它
__chkstk
中的堆栈溢出使进程崩溃因为它使用一些内存地址而不是闭包大小作为访问内存页面的“计数器”:
Exception thrown at 0x00007FF7E41FE948 in example.exe: 0xC00000FD: Stack overflow (parameters: 0x0000000000000001, 0x000000EFEDC06000).
__chkstk()
第 109 行 (d:\agent_work\5\s\src\vctools\crt\vcstartup\src\misc\amd64\chkstk.asm) std::alloc::boxed::{{impl}}::call_once<(), FnOnce<()>>(core::ops::function::Box<FnOnce<()>> self)
第 1015 行 (boxed.rs) std::alloc::boxed::{{impl}}::call_once<(), alloc::boxed::Box<FnOnce<()>>>(core::ops::function::Box<FnOnce<()>> * self)
第 1015 行 (boxed.rs) try_spawn_std_like::thread_start(unsigned char * main)
(main.rs) try_spawn_std_like::<closure-0, ()>(main::closure-0)
(main.rs) spawn_std_like<closure-0, ()>(main::closeure-0 f)
(main.rs) main()
(main.rs) // Explicitly typed out, `std` style.
fn spawn0<F, T>(f: F) -> Result<Handle, ()>
where
F: FnOnce() -> T,
F: Send + 'static,
T: Send + 'static,
{
extern "system" fn thread_start(f: *mut u8) -> u32 {
let f = f as *mut Box<dyn FnOnce()>;
let f: Box<Box<dyn FnOnce()>> = unsafe {
Box::from_raw(f)
};
f();
0
}
let p = Box::new(Box::new(f));
let handle = CreateThread(
thread_start,
&*p as *const _ as *mut _
);
if handle.0 != 0 {
core::mem::forget(p);
Ok(handle)
} else {
Err(())
}
}
// Explicitly typed out, with `into_raw`.
fn spawn1<F, T>(f: F) -> Result<Handle, ()>
where
F: FnOnce() -> T,
F: Send + 'static,
T: Send + 'static,
{
extern "system" fn thread_start(f: *mut u8) -> u32 {
let f = f as *mut Box<dyn FnOnce()>;
let f: Box<Box<dyn FnOnce()>> = unsafe {
Box::from_raw(f)
};
f();
0
}
let f: Box<Box<F>> = Box::new(Box::new(f));
let f: *mut Box<F> = Box::into_raw(f);
let handle = CreateThread(
thread_start,
f as *mut _
);
if handle.0 != 0 {
Ok(handle)
} else {
unsafe { Box::from_raw(f); }
Err(())
}
}
// Implicitly typed `spawn1` variant.
fn spawn2<F, T>(f: F) -> Result<Handle, ()>
where
F: FnOnce() -> T,
F: Send + 'static,
T: Send + 'static,
{
extern "system" fn thread_start(f: *mut u8) -> u32 {
unsafe {
Box::from_raw(
f as *mut Box<dyn FnOnce()>
)();
}
0
}
let f = Box::into_raw(Box::new(Box::new(f)));
let handle = CreateThread(
thread_start,
f as *mut _
);
if handle.0 != 0 {
Ok(handle)
} else {
unsafe { Box::from_raw(f); }
Err(())
}
}
// Generic `thread_start` routine.
fn spawn3<F, T>(f: F) -> Result<Handle, ()>
where
F: FnOnce() -> T,
F: Send + 'static,
T: Send + 'static,
{
extern "system" fn thread_start<F, T>(f: *mut Box<F>) -> Handle
where
F: FnOnce() -> T,
F: Send + 'static,
T: Send + 'static
{
unsafe { Box::from_raw(f)(); }
Handle(1)
}
let f = Box::into_raw(Box::new(Box::new(f)));
let handle = thread_start(f);
if handle.0 != 0 {
Ok(handle)
} else {
unsafe { Box::from_raw(f); }
Err(())
}
}
// More explicit type in type-cast in `thread_start`. Does not compile.
/*
fn spawn4<F, T>(f: F) -> Result<Handle, ()>
where
F: FnOnce() -> T,
F: Send + 'static,
T: Send + 'static,
{
extern "system" fn thread_start(f: *mut u8) -> u32 {
unsafe {
Box::from_raw(
// f as *mut Box<dyn FnOnce() -> (dyn Send + 'static) + Send + 'static>
// f as *mut Box<dyn FnOnce() -> (dyn Sized + Send + 'static) + Send + 'static>
)();
}
0
}
let f = Box::into_raw(Box::new(Box::new(f)));
let handle = CreateThread(
thread_start,
f as *mut _
);
if handle.0 != 0 {
Ok(handle)
} else {
unsafe { Box::from_raw(f); }
Err(())
}
}
*/
// Like `spawn2`, but with `+ Send + 'static`.
fn spawn5<F, T>(f: F) -> Result<Handle, ()>
where
F: FnOnce() -> T,
F: Send + 'static,
T: Send + 'static,
{
// `kernel32.CreateThread` like start routine.
extern "system" fn thread_start(f: *mut u8) -> u32 {
unsafe {
Box::from_raw(
f as *mut Box<dyn FnOnce() + Send + 'static>
)();
}
0
}
let f = Box::into_raw(Box::new(Box::new(f)));
let handle = CreateThread(
thread_start,
f as *mut _
);
if handle.0 != 0 {
Ok(handle)
} else {
unsafe { Box::from_raw(f); }
Err(())
}
}
spawn3
以外的所有版本闭包中的实际代码被编译器从二进制文件中剥离出来,因此它永远无法工作。我在最小的
#[no_std]
中尝试过这个通过调用
user32.MessageBox
来装箱在闭包中,它不会出现在二进制文件内的导入函数列表中。它还在我的
__chkstk
实现中崩溃。 .我可以在调试时看到参数发送到
rax
中的函数register(特殊调用约定)包含一个内存地址而不是闭包的大小,它每次将循环中的参数递减 0x1000 并触摸堆栈页面,直到堆栈溢出。
kernel32.CreateThread
spawn3
是唯一有效的变体。但我不能将它用于真正的
kernel32.CreateThread
,因为导入的 C 函数及其参数在 Rust 中不能是泛型的 (
error[E0044]: foreign items may not have type parameters
):
#[link(name = "kernel32", kind = "dylib")]
extern "system" {
fn CreateThread<
F: Send + 'static + FnOnce() -> T,
T: Send + 'static
>(
security_attributes: *const u8,
stack_size: usize,
start_address: extern "system" fn(*mut Box<F>) -> u32,
parameter: *mut Box<F>,
attributes: u32,
id: *mut u32
) -> usize;
}
最佳答案
在线上
let p = Box::new(Box::new(f));
Box<Box<F>>
.这里的两个框是细指针,因为
F
恰好是
Sized
在这里,因为
Box<T>
总是
Sized
.
unsafe { Box::from_raw(main as *mut Box<dyn FnOnce()>)(); }
Box
作为
Box<dyn FnOnce()>
.
Box<dyn FnOnce()>
是一个胖指针:一个原始指针加上一些辅助数据——在
dyn Trait
的情况下类型,辅助数据是指向 vtable 的指针。
Box<dyn FnOnce()>
.为此,您需要转换内部
Box
, 像这样:
let p = Box::new(Box::new(f) as Box<dyn FnOnce()>);
F
实现
FnOnce() -> T
,而不是
FnOnce()
(它是
FnOnce() -> ()
的简写)。改变界限
F: FnOnce() -> T
至
F: FnOnce()
并删除现在多余的
T
在
spawn_std_like
和
try_spawn_std_like
将解决这个问题。另一种选择是包装
f
在返回
()
的闭包中:
let p = Box::new(Box::new(|| { f(); }) as Box<dyn FnOnce()>);
关于multithreading - 复制 `std::thread::spawn` 导致堆栈溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59771881/
我正在编写一个应用程序,允许用户创建一个“问卷”,然后向其中添加问题。我正在使用核心数据来存储信息。我创建了一个问卷实体,并与问题实体建立了“一对多”关系。我的问题是,如果要允许用户复制(复制)整个调
有没有办法复制或复制 SharedPreference?或者我需要从一个变量中获取每个变量,然后将它们放入另一个变量中吗? 最佳答案 尝试这样的事情: //sp1 is the shared pref
下面的(A)和(B)有区别吗? (假设 NON ARC,如果重要的话) // --- (A) --- @interface Zoo : NSObject{} @property (copy) Dog
我正在尝试将 mysql SELECT 查询保存到文件中,如下所示: $result = mysqli_query($db,$sql); $out = fopen('tmp/csv.csv', 'w'
我需要创建一个 CVPixelBufferRef 的副本,以便能够使用副本中的值以按位方式操作原始像素缓冲区。我似乎无法使用 CVPixelBufferCreate 或 CVPixelBufferCr
我在 Source 文件夹中有一个 Active wave 录音 wave-file.wav。我需要使用新名称 wave-file-copy.wav 将此文件复制到 Destination 文件夹。
在使用 GNU Autotools 构建的项目中,我有一个脚本需要通过 make 修改以包含安装路径。这是一个小例子: configure.ac: AC_INIT(foobar, 1.0) AC_PR
我想将 SQL 的行复制到同一个表中。但是在我的表中,我有一个“文本”列。 使用此 SQL: CREATE TEMPORARY TABLE produit2 ENGINE=MEMORY SELECT
谁能给我解释一下 df2 = df1 df2 = df1.copy() df3 = df1.copy(deep=False) 我已经尝试了所有选项并执行了以下操作: df1 = pd.DataFram
Hazelcast 是否具有类似于 Ehcache 的复制? http://www.ehcache.org/generated/2.9.0/pdf/Ehcache_Replication_Guide.
我有以下拓扑。一个 Ubuntu 16.04。运行我的全局 MySQL 服务器的 Amazon AWS 上的实例。我想将此服务器用作许多本地主服务器(Windows 机器 MySQL 服务器)的从服务
使用 SQLyog,我正在测试表中是否设置了正确的值。我尝试过 SELECT type_service FROM service WHERE email='test@gmail.com' 因此,只输出
有人可以提供一些关于如何配置 ElasticSearch 进行复制的说明。我在 Windows 中运行 ES,并且了解如果我在同一台服务器上多次运行 bat 文件,则会启动一个单独的 ES 实例,并且
一 点睛 ThreadGroup 复制线程的两个方法。 public int enumerate(Thread list[]) // 会将 ThreadGroup 中的 active 线程全部复制到
一 点睛 ThreadGroup 复制线程组的两个方法。 public int enumerate(ThreadGroup list[]) // 相对于 enumerate(list,true) pu
官方documentation Cassandra 说: Configure the keyspace and create the new datacenter: Use ALTER KEYSPAC
This question already has answers here: How to weight smoothing by arbitrary factor in ggplot2? (2个答
我们有一个表格来表明对各种俱乐部的兴趣。输出将数据记录在 Excel 电子表格中,其中列有他们的首选姓名、姓氏、电子邮件、代词,以及他们感兴趣的俱乐部的相应列中的“1”(下面的模型)。 我们希望为俱乐
This question already has answers here: Closed 8 years ago. Possible Duplicate: In vim, how do I get
如何复制形状及其所在的单元格?当我手动复制时,形状会跟随单元格,但是当我使用宏进行复制时,我会得到除形状之外的所有其他内容。 Cells(sourceRow, sourceColumn).Copy C
我是一名优秀的程序员,十分优秀!