我目前正在一个使用很多lambda函数的项目中工作,我发现它们使用了很多堆栈,但是我不明白为什么。对C ++来说我是一个新手,对C来说我更习惯了。
为了尝试减少堆栈使用量并了解lambda的工作原理,我编写了一些非常简单的代码来重现我们对lambda的使用。我正在用gcc和-Os选项编译以下代码。
typedef struct structTest
{
uint32_t var1;
uint32_t var2;
} structTest;
// Test 1
int main()
{
dostuff( [&]() -> structTest{ structTest $; $.var2 = 24; $.var1 = 48; return $; }() );
}
// Test 2
int main()
{
dostuff( [&]() -> structTest{ structTest $; $.var2 = 24; $.var1 = 48; return $; }() );
dostuff( [&]() -> structTest{ structTest $; $.var2 = 13; $.var1 = 42; return $; }() );
}
测试1使用8字节的堆栈,这并不是我真正期望的,但是可以理解,但是测试2使用16字节的堆栈,我不明白为什么。我本来希望有8个字节,因为在函数的第一次调用使用的堆栈中,第二次调用将重用该堆栈。
我猜想这两个结构不会在堆栈上保留。
用臭氧分析烟囱,并在Nucleo L476RG上运行。此项目是IoT项目,其中ROM和堆栈非常宝贵。有没有一种方法可以保持这种结构/ lambda使用率但减少堆栈使用率?
答案 0 :(得分:1)
像这样的lambda的主要好处之一是,它们可以很容易地内联到周围的代码中。这就是为什么我们喜欢他们!没有新堆栈或跳转之类的开销。
当然,内联伴随着使用周围函数的堆栈来存储所有数据。那就是你所观察到的。
在任何其他“我不希望将其内联”的情况下,请执行您将要执行的任何操作。在这种特定情况下,也许使用实际函数而不是lambda,并在它们上添加一个“ noinline”类型的属性(有关方法,请参见工具链的文档)。
如果您想举一个为什么人们不经常使用C ++进行嵌入式编程的例子,那将是一个很好的例子。它专为更复杂的处理器而设计,在这些处理器中,我们通常实际上并不关心是否还要再使用8个字节的堆栈-我们关心程序是否能够快速运行,并且我们信任编译器通过内联有意义的代码来帮助我们做到这一点这样做。您的环境和要求完全不符合该社会契约。
肯定会重做或超载dostuff
,因此您可以这样称呼它:
dostuff(48, 24);
…会更好吗?
实现可能很简单:
__attribute__((noinline))
void doStuff(const uint32_t var1, const uint32_t var2)
{
const structTest sT = {var1, var2};
doStuff(sT);
}
它的代码也少得多,而且IMO更易于阅读。
顺便说一句,尽管它可以在您的平台上使用,但我实际上并不建议使用$
作为标识符。它是non-standard to a degree,对读者来说不是很清楚。