GCC中返回std::variant时-Wstack-usage栈使用量计算错误
问题描述
struct TestStruct { std::array<char, 100> bigBoi{}; }; std::variant<TestStruct> GetVariant() { return TestStruct{}; return TestStruct{}; }
禁用优化(-O0)时,GetVariant()函数会被-Wstack-usage标记为栈使用量超过TestStruct中数组大小的两倍;开启-O1优化后,该警告消失。
更具代表性的实际场景代码:
std::variant<TestStruct> GetVariant(ENUM enum) { switch (enum) { case CASE1: return TestStruct{}; case CASE2: return TestStruct{}; } }
补充说明:直接返回TestStruct的函数无此问题,说明问题确实与std::variant相关:
TestStruct GetStruct() { return TestStruct{}; return TestStruct{}; }
请问这是否属于编译器bug?
结论
这不属于编译器bug,是未优化模式下的栈使用统计逻辑导致的正常现象。
在-O0(无优化)模式下,编译器会保留代码的原始执行逻辑,不会启用返回值优化(RVO)或省略临时对象。对于返回std::variant的函数,每个return TestStruct{}语句都会先在栈上创建一个TestStruct临时对象,再将该临时对象构造到std::variant的返回值存储区中——这意味着栈上会同时存在至少两个TestStruct实例的空间(临时对象+variant内部存储),-Wstack-usage的统计会把这些临时对象的栈空间全部计入,从而触发警告。
开启-O1及以上优化后,编译器会执行返回值优化,直接在std::variant的返回值存储区构造TestStruct对象,避免了临时对象的栈空间占用,因此警告消失。
而直接返回TestStruct的函数在-O0下无此问题,是因为C++标准对类类型返回值的处理逻辑特殊,即使无优化,编译器也可能直接在调用者的栈帧中构造返回对象,或复用存储,不会产生额外的临时对象栈开销。
内容的提问来源于stack exchange,提问作者Lukas Vozenilek
相关产品推荐
相关产品推荐

