gpt4 book ai didi

c++ - 使用 clang 优化进行编译时出现意外结果

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:03:51 26 4
gpt4 key购买 nike

我在我的代码中发现了一个错误,只有当我启用编译器优化 -O1 或更高时才会发生。我跟踪了这​​个错误,似乎在启用优化时我无法在 boost 转换范围上使用 boost 类型删除适配器。我写了这个 c++ 程序来重现它:

#include <iostream>
#include <vector>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/adaptor/type_erased.hpp>

using namespace boost::adaptors;
using namespace std;

int addOne(int b) {
return b + 1;
}

int main(int, char**) {
vector<int> nums{ 1, 2, 3 };

auto result1 = nums | transformed(addOne) | type_erased<int, boost::forward_traversal_tag>();
auto result2 = nums | transformed(addOne);
auto result3 = nums | type_erased<int, boost::forward_traversal_tag>();

for (auto n : result1)
cout << n << " ";
cout << endl;

for (auto n : result2)
cout << n << " ";
cout << endl;

for (auto n : result3)
cout << n << " ";
cout << endl;
}

当我在没有任何优化的情况下运行这个程序时,我得到以下输出:

2 3 4
2 3 4
1 2 3

当我使用 -O1 标志运行它时,我得到以下信息:

1 1 1
2 3 4
1 2 3

我正在使用 clang++ 来编译它。我使用的 clang 版本是:

Apple LLVM 版本 8.0.0 (clang-800.0.38)

我不知道是我做错了什么,还是 boost/clang 错误。

编辑:

改成

type_erased<int, boost::forward_traversal_tag, const int>()

现在可以使用了。第三个模板参数是引用类型,将引用设置为 const 会延长转换后创建的临时对象的时间跨度。

最佳答案

编辑 事实上,这不仅仅是表面上看到的。还有另一个可用性问题,它确实解决了这个问题。参见 OP's self-answer


您正陷入 Boost Range v2(和 Boost Proto 等)的第一个陷阱。

nums | transformed(addOne) 是临时的。 type_erased 适配器存储对此的引用

将类型删除的适配器分配给 resultN 变量后,临时对象被销毁。

你有一个悬空引用:(

这是一个非常不直观的效果,也是我限制在我的代码库中使用 Range V2 的第一个原因:我经常遇到这种情况。

解决方法如下:

auto tmp = nums | transformed(addOne);
auto result = tmp | type_erased<int, boost::forward_traversal_tag>();

-fsanitize=address,undefined 确认 UB 在使用命名的临时文件时消失了。

关于c++ - 使用 clang 优化进行编译时出现意外结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40479397/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com