Memory Rust是否在堆栈上进行分配,以使用某些参数初始化选项引用?
我一直在受限嵌入式环境(在STM32F303 MCU上)中使用Rust,我注意到我的一些函数分配了出乎意料的大量堆栈空间。 在这种环境中,我没有分配器,需要在堆栈上分配大型、可变的静态数据结构。 最终,我发现一些函数意外地在堆栈上分配空间,导致内存受限的堆栈溢出 我希望了解以下Memory Rust是否在堆栈上进行分配,以使用某些参数初始化选项引用?,memory,rust,embedded,stack-overflow,option-type,Memory,Rust,Embedded,Stack Overflow,Option Type,我一直在受限嵌入式环境(在STM32F303 MCU上)中使用Rust,我注意到我的一些函数分配了出乎意料的大量堆栈空间。 在这种环境中,我没有分配器,需要在堆栈上分配大型、可变的静态数据结构。 最终,我发现一些函数意外地在堆栈上分配空间,导致内存受限的堆栈溢出 我希望了解以下mutate函数需要在堆栈上分配多少内存。 我一直在这个网站上寻找这个问题的答案,但似乎没有人能回答这个更普遍的问题。 我知道,对于下面的代码块,我可以查看LLVM/程序集以了解分配的位置,但我试图了解如何预测何时为一类一
mutate
函数需要在堆栈上分配多少内存。
我一直在这个网站上寻找这个问题的答案,但似乎没有人能回答这个更普遍的问题。
我知道,对于下面的代码块,我可以查看LLVM/程序集以了解分配的位置,但我试图了解如何预测何时为一类一般问题分配堆栈—独立于编译器选项和优化器。
下面的问题是一个玩具示例,它模拟了我在嵌入式Rust程序中使用的模式(并且存在问题)
问题:下面的mutate
需要在堆栈上分配多少内存?
结构父级{
数据:选项,
}
内隐父代{
pub fn new()->Self{
父项{数据:无}
}
//理想情况下,此函数应该在堆栈上分配可忽略不计的内存
pub fn mutate(&mut self){
设arr=[0u32;1024];
self.data=Some(arr);
对于0..self.data.unwrap().len()中的i{
self.data.unwrap()[i]=i作为u32;
}
}
}
fn main(){
让mut it=Parent::new();
it.mutate();
}
考虑
- 其他帖子似乎暗示这种行为取决于优化器。如果是这种情况,有没有办法重写上面的代码,使每个函数的堆栈分配大小对代码的读者来说都是显而易见的
- let关键字(mutate函数中的第一行)是否对是否在堆栈上分配大数组有任何影响
- 我确信我可以使用
不安全的
rust来确保此函数不需要进行任何分配/memcpys(就像我在C中所做的那样)。有没有更好的方法不用
不安全的
父结构必然也需要4kB,事实上,选项的标记可能需要4kB+4或8字节(不确定u32数组的对齐要求是什么),因为数组没有rustc可用于小生境变量优化的无效值
编辑:哦,等等,不,您还可以使用self.data.unwrap()
调用将数组复制回函数中,这样就多了两个调用,至少12kB。事实上,将其插入编译器资源管理器会告诉我:
示例::父::mutate:
mov eax,28856
这是28k,不太清楚这些额外演员是从哪里来的
无论如何,激活-O
,看起来一切都得到了优化,所以…幸运吗?:
example::Parent::mutate:
push rax
mov dword ptr [rdi], 1
add rdi, 4
mov edx, 4096
xor esi, esi
call qword ptr [rip + memset@GOTPCREL]
pop rax
ret
谢谢你的回复。我希望重写mutate函数,这样它就不需要在堆栈上分配内存,而是使用父结构中已经分配的内存。是否有一种方法可以编写此函数,使其内存占用可以忽略不计—与优化器无关?@KevinKellar从结构中删除选项
(没有间接寻址,实际上不会保存任何内存),然后在成员上工作?如果您坚持使用选项
成员,那么使用If let Some(a)=self.data.as_mut(){iterate and operate array here}
之类的方法将有助于在选项中获得指向数组的引用(指针),而不是将数据移入移出。我不会使用该选项来节省内存。在我的程序中,父结构需要能够在不初始化选项中的数据的情况下进行构造-因此在构造函数中它被设置为“无”。如果父结构的字段是一个选项,我如何在不必为mutate的stackframe上的整个Otherstruct分配空间的情况下将self.data初始化到一些?在C语言中,函数可以获取一个指向选项中统一内存的指针,并使用该指针改变内存。但是在rust中,我可以引用某个选项的某个变量,但将数据保留在某个未初始化的变量中吗?我正在寻找一种方法来重写mutate函数,使其不分配独立于编译器/优化器设置的内存。如果您认为该选项可以避免使用数组大小,那么您就错了。我不明白你期望什么。。。这看起来像是xy方差问题。有什么问题吗?我希望您认识到整个for
循环没有任何作用,因为每个unwrap()
都会复制整个数组。感谢您的回答。我知道这里的选项将分配比数组大小更多的空间,并且不能用于节省空间。在我的程序中,父结构可能处于多种状态,其中一种状态是数组尚未准备好使用,另一种状态是数组已被成员函数初始化为某些状态,并准备好用于计算。数组元素的变异不需要复制任何内容(除了变异时的单个值)。您是在复制数组而不是变异数组。基本上,除了[u32;1024]
是复制
,因此不存在所有权问题。如果