Memory Rust是否在堆栈上进行分配,以使用某些参数初始化选项引用?

Memory Rust是否在堆栈上进行分配,以使用某些参数初始化选项引用?,memory,rust,embedded,stack-overflow,option-type,Memory,Rust,Embedded,Stack Overflow,Option Type,我一直在受限嵌入式环境(在STM32F303 MCU上)中使用Rust,我注意到我的一些函数分配了出乎意料的大量堆栈空间。 在这种环境中,我没有分配器,需要在堆栈上分配大型、可变的静态数据结构。 最终,我发现一些函数意外地在堆栈上分配空间,导致内存受限的堆栈溢出 我希望了解以下mutate函数需要在堆栈上分配多少内存。 我一直在这个网站上寻找这个问题的答案,但似乎没有人能回答这个更普遍的问题。 我知道,对于下面的代码块,我可以查看LLVM/程序集以了解分配的位置,但我试图了解如何预测何时为一类一

我一直在受限嵌入式环境(在STM32F303 MCU上)中使用Rust,我注意到我的一些函数分配了出乎意料的大量堆栈空间。 在这种环境中,我没有分配器,需要在堆栈上分配大型、可变的静态数据结构。 最终,我发现一些函数意外地在堆栈上分配空间,导致内存受限的堆栈溢出

我希望了解以下
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(32=8*1024)?实际上,您正在堆栈上创建一个本地数组,Rust没有新的放置位置,因此即使您没有在堆栈上创建本地数组,也基本上取决于处理分配的优化程序

还要注意的是,您的
父结构必然也需要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]
复制
,因此不存在所有权问题。如果