gpt4 book ai didi

c++ - 为什么编译器会在某些优化级别警告未初始化的边迭代器?

转载 作者:行者123 更新时间:2023-12-03 10:05:49 25 4
gpt4 key购买 nike

我已经尽可能地最小化了可重现的例子。在其中,我遍历了 boost 图中的所有边,并收到了一个我不明白的警告。请向我解释为什么我会收到这个警告,也许还有为什么它只出现在某些优化级别。

/*
* reproducing the warning about maybe uninitialized edge iterator
*/
#include <vector>
#include <iostream>
#include <boost/graph/adjacency_list.hpp>

typedef boost::adjacency_list_traits<boost::vecS, boost::vecS, boost::directedS> traits;
typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, boost::no_property,
boost::property<boost::edge_capacity_t, long>> graph;

typedef traits::vertex_descriptor vertex_desc;
typedef traits::edge_descriptor edge_desc;
typedef boost::graph_traits<graph>::edge_iterator edge_iterator;

int main(){
// build a graph
graph G(10);
// get its capacity map
auto c_map = boost::get(boost::edge_capacity, G);
// get a handle to the first vertex
vertex_desc source = boost::vertex(0, G);
// add an edge, with a capacity of 1
edge_desc e = boost::add_edge(boost::vertex(0, G), boost::vertex(1, G), G).first;
c_map[e] = 1;
// loop over all edges in the graph
std::pair<edge_iterator, edge_iterator> eip = boost::edges(G);
for (edge_iterator eit = eip.first; eit != eip.second; eit++){
edge_desc e = *eit;
vertex_desc a = boost::source(e, G);
vertex_desc b = boost::target(e, G);
bool source_involved = ((a == source) || (b == source));
std::cout << (source_involved ? "yes" : "no") << std::endl;
}
}
编译 -O0-O1 ,没有警告:
g++ -std=c++14 -Wall -Wextra -O0 repro.cpp -o repro.exe
编译 -O2我收到此警告:
# g++ -std=c++14 -Wall -Wextra -O2 repro.cpp -o repro.exe
repro.cpp: In function 'int main()':
repro.cpp:28:24: warning: '*((void*)& eit +48)' may be used uninitialized in this function [-Wmaybe-uninitialized]
for (edge_iterator eit = eip.first; eit != eip.second; eit++){
^~~
并用 -O3 编译, -O4 , -O5我收到了类似的警告,但很难看:
# g++ -std=c++14 -Wall -Wextra -O3 repro.cpp -o repro.exe
repro.cpp: In function 'int main()':
repro.cpp:28:24: warning: '*((void*)(& eit)+32).__gnu_cxx::__normal_iterator<boost::detail::stored_edge_property<long unsigned int, boost::property<boost::edge_capacity_t, long int> >*, std::vector<boost::detail::stored_edge_property<long unsigned int, boost::property<boost::edge_capacity_t, long int> >, std::allocator<boost::detail::stored_edge_property<long unsigned int, boost::property<boost::edge_capacity_t, long int> > > > >::_M_current' may be used uninitialized in this function [-Wmaybe-uninitialized]
for (edge_iterator eit = eip.first; eit != eip.second; eit++){
我的 g++ --version
g++ (Ubuntu 8.4.0-1ubuntu1~18.04) 8.4.0
我在 docker 中运行
# uname -a
Linux 88157d45c773 5.4.0-58-generic #64~18.04.1-Ubuntu SMP Wed Dec 9 17:11:11 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
警告确实出现在 -std=c++11 中和 -std=c++14但不在 -std=c++17 , 它似乎。
这个警告告诉我什么?问题是什么?

最佳答案

正如我所评论的,这可能是特定编译器版本的编译器问题,其中内联 + 死代码省略会导致虚假的未使用变量警告。
我认为查找是否存在与修复相关的错误报告并没有什么好处。相反,让我向您展示在 c++14 中编写代码的更优雅的方法。

Not intended as an answer to the question as posed. though by sheer coincidence, the specific warnings you encounter might be gone.

I post the answer for inspiration/educational value as I see a lot of copy/past BGL that is badly behind the times.


Live On Wandbox
#include <boost/graph/adjacency_list.hpp>
#include <iostream>
#include <vector>

using capacity_prop = boost::property<boost::edge_capacity_t, long>;

using graph = boost::adjacency_list<
boost::vecS, boost::vecS, boost::directedS,
boost::no_property, capacity_prop
>;

int main() {
graph G(10);
auto add = [&G](auto a, auto b, auto c) {
add_edge(vertex(a, G), vertex(b, G), capacity_prop{c}, G);
};
add(0, 1, 1);
add(1, 2, 2);
add(1, 3, 3);
add(1, 7, 4);
add(1, 8, 5);
add(2, 5, 6);
add(5, 3, 7);
add(5, 0, 8);
add(7, 0, 9);

auto const s = vertex(0, G);

for (auto e : boost::make_iterator_range(edges(G))) {
auto a = source(e, G);
auto b = target(e, G);
std::cout << e << " involves " << s << "? "
<< std::boolalpha << (a == s || b == s) << std::endl;
}
}
打印
(0,1) involves 0? true
(1,2) involves 0? false
(1,3) involves 0? false
(1,7) involves 0? false
(1,8) involves 0? false
(2,5) involves 0? false
(5,3) involves 0? false
(5,0) involves 0? true
(7,0) involves 0? true
C++17 奖金
更自然地编写初始化代码会更容易
for (auto [a,b,c] : { std::tuple
{0, 1, 1}, {1, 2, 2}, {1, 3, 3},
{1, 7, 4}, {1, 8, 5}, {2, 5, 6},
{5, 3, 7}, {5, 0, 8}, {7, 0, 9}, })
{
add_edge(vertex(a, G), vertex(b, G), capacity_prop{c}, G);
}
逻辑奖金
如果您真的只想找到涉及顶点的边集 s ,你可以这样写,可能会更有效率:
Live On Wandbox
auto const s = vertex(2, G); // different example
auto [f,l] = out_edges(s, G);
edge_set involved(f, l);

for (auto e : make_iterator_range(edges(G)))
if (target(e, G) == s)
involved.insert(e);

for (auto e : involved)
std::cout << e << " ";
打印
(1,2) (2,5) 
正如人们所料。
性能提示
如果您可以调整图形模型,通过更改它以维护 adjacency_list 的双向边,可以获得更好的性能:
std::set<graph::edge_descriptor> involved;

auto insert = [&](auto range) { involved.insert(range.first, range.second); };
insert(out_edges(s, G));
insert(in_edges(s, G));
或者,实际上,只需立即打印它们:
for (auto e : make_iterator_range(out_edges(s, G)))
std::cout << e << " ";
for (auto e : make_iterator_range(in_edges(s, G)))
std::cout << e << " ";
看看 Live Ob Wandbox
打印一样。

Whether or not this improves performance for your application depends mostly on whether you have more mutations or more queries on the graph.


聚苯乙烯
这是我为示例制作的图表以供引用
enter image description here
这是做的结果
boost::dynamic_properties dp;
dp.property("node_id", get(boost::vertex_index, G));
dp.property("label", get(boost::edge_capacity, G));
write_graphviz_dp(std::cout, G, dp);
并使用 dot (例如 online )

关于c++ - 为什么编译器会在某些优化级别警告未初始化的边迭代器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65506467/

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