g++优化使程序无法运行
g++ optimization makes the program unable to run
我实现了一个基于D*-Lite的路径规划算法。当我不打开优化(-O0)时,程序可以正常运行。但是当我打开优化级别(-O1/2/3)时,程序无法终止。在Visual Studio下,debug模式和release模式都可以正常运行。以上情况,代码都是一样。我不知道怎么找到问题,谁能帮帮我?
class DstarLite {
public:
DstarLite() = delete;
DstarLite(GridStatus* a, GridStatus* b, FILE* fp)
: k_m_(0), start_(a), last_(start_), goal_(b), open_close_(fp) {}
void calculateKey(GridStatus* s);
void updateVertex(GridStatus* u);
void initialize();
void computeShortestPath();
void rePlanning(vector<pair<GridStatus*, int>>& node_change);
GridStatus* getStart();
void setStart(GridStatus* val);
GridStatus* getGoal();
private:
Fib frontier_;
double k_m_;
unordered_map<GridStatus*, handle_t>
heap_map_;
GridStatus* start_;
GridStatus* last_;
GridStatus* goal_;
FILE* open_close_;
};
void DstarLite::calculateKey(GridStatus* s) {
s->f = min(s->g, s->rhs) + heuristic(start_, s) + k_m_;
s->k2 = min(s->g, s->rhs);
}
void DstarLite::initialize() {
fprintf(open_close_, "%d %d\n", start_->x, start_->y);
fprintf(open_close_, "%d %d\n", goal_->x, goal_->y);
goal_->rhs = 0;
calculateKey(goal_);
handle_t hand = frontier_.push(goal_);
heap_map_[goal_] = hand;
}
void DstarLite::updateVertex(GridStatus* u) {
bool heap_in = heap_map_.find(u) != heap_map_.end();
if (u->g != u->rhs && heap_in) {
calculateKey(u);
frontier_.update(heap_map_[u]);
} else if (u->g != u->rhs && !heap_in) {
calculateKey(u);
handle_t hand = frontier_.push(u);
heap_map_[u] = hand;
} else if (u->g == u->rhs && heap_in) {
calculateKey(u);
frontier_.erase(heap_map_[u]);
heap_map_.erase(u);
}
}
void DstarLite::computeShortestPath() {
int count = 0;
while (smaller(frontier_.top(), start_) || !myEqual(start_->rhs, start_->g)) {
count++;
auto u = frontier_.top();
pair<double, double> k_old = {u->f, u->k2};
pair<double, double> k_new;
k_new.first = min(u->g, u->rhs) + heuristic(start_, u) + k_m_;
k_new.second = min(u->g, u->rhs);
if (k_old < k_new) {
calculateKey(u);
frontier_.update(heap_map_[u]);
} else if (myGreater(u->g, u->rhs)) {
u->g = u->rhs;
frontier_.pop();
heap_map_.erase(u);
for (auto s : neighbors(u)) {
if (s->rhs > u->g + cost(u, s)) {
s->next = u;
s->rhs = u->g + cost(u, s);
updateVertex(s);
}
}
} else {
double g_old = u->g;
u->g = kDoubleInfinity;
auto neighbor = neighbors(u);
neighbor.push_back(u);
for (auto s : neighbor) {
if (myEqual(s->rhs, cost(s, u) + g_old)) {
if (!equal(s, goal_)) {
double pp_s = kDoubleInfinity;
for (auto succ : neighbors(s)) {
double dis = succ->g + cost(succ, s);
if (dis < pp_s) {
pp_s = dis;
s->next = succ;
}
}
s->rhs = pp_s;
}
}
updateVertex(s);
}
}
}
cout << "Dstar visited nodes : " << count << endl;
}
void DstarLite::rePlanning(vector<pair<GridStatus*, int>>& node_change) {
k_m_ += heuristic(last_, start_);
last_ = start_;
for (auto change : node_change) {
GridStatus* u = change.first;
int old_threat = u->threat;
int new_threat = change.second;
double c_old;
double c_new;
u->threat = new_threat;
u->rhs += (new_threat - old_threat) * threat_factor;
updateVertex(u);
for (auto v : neighbors(u)) {
u->threat = old_threat;
c_old = cost(v, u);
u->threat = new_threat;
c_new = cost(v, u);
if (c_old > c_new) {
if (v != goal_) {
if (v->rhs > u->g + c_new) {
v->next = u;
v->rhs = u->g + c_new;
}
}
} else if (myEqual(v->rhs, c_old + u->g)) {
if (v != goal_) {
double pp_s = kDoubleInfinity;
for (auto pre : neighbors(v)) {
double dis = pre->g + cost(pre, v);
if (dis < pp_s) {
pp_s = dis;
v->next = pre;
}
}
v->rhs = pp_s;
}
}
updateVertex(v);
}
}
}
GridStatus* DstarLite::getStart() { return start_; }
void DstarLite::setStart(GridStatus* val) { start_ = val; }
GridStatus* DstarLite::getGoal() { return goal_; }
DstarLite dstar(start, goal, open_close);
dstar.initialize();
dstar.computeShortestPath();
抱歉,我觉得很难定位到代码中的问题,所以之前没有展示代码。现在重新编辑了题目,但是代码很多,主要调用部分是computeShortest().
由于您没有提供任何代码,我们只能给您一些一般提示来解决此类问题。
作为第一个假设,您的代码肯定存在一个或多个导致我们称之为 undefined behaviour UB 的错误。由于结果是未定义的,它可以是任何东西,并且经常随着不同的优化级别、编译器版本或平台改变行为。
你能做什么:
启用所有警告并修复它们!特别寻找诸如“比较总是...”、“使用 xxx(有时)未初始化”、“无效指针转换”之类的内容,...
尝试在不同的编译器上编译。您还应该尝试使用 gcc and/or clang,即使在 windows 上也是如此。第一次在 windows 平台上获取这些编译器 运行 的环境可能很难,但确实值得这样做。不同的编译器会给出不同的警告。修复来自所有编译器的所有警告是一个非常好的帮助!
你应该使用像 valgrind
这样的内存跟踪器。我对 windows 的经验不多,但我相信也有这样的工具,也许已经集成到您的开发套件中了。这些工具非常适合查找“of by x”访问、访问释放的内存等问题。
如果您仍然运行遇到这样的麻烦,静态代码分析器工具可能会有所帮助。通常不像管理人员认为的那么多,因为今天的编译器通过检测恐龙程序员所期望的缺陷要好得多。额外的发现通常是误报,尤其是当您使用现代 C++ 时。通常,您可以省下这笔钱并参加 class 的教育!
评论,评论,与其他人一起评论!
把问题剪短!您应该将大部分开发时间花在设置良好的自动化单元测试上。检查每个路径,每个文件中的每个函数。很高兴看到至少 95% 的分支被测试覆盖。如果您更改优化器级别和/或编译器和平台,如果您的代码中有 UB,通常这些测试也会失败。
使用调试器可能会令人沮丧。在高度优化的代码中,您会跳过所有内容而什么都不会,您可能无法真正看到您在哪里以及与您的代码有什么关系。如果在较低的优化器级别中不存在错误,那么您实际上没有太多机会找到潜在的问题。
最后但同样重要的是:“printf 调试”。但这也可能会改变行为。在最坏的情况下,如果您添加调试输出,代码将始终 运行。但这是一个机会!
使用编译器中的线程和内存清理器。
问题是浮点数比较引起的。之前写代码的时候特意搁置了这个问题:)。修复后可以正常运行
我实现了一个基于D*-Lite的路径规划算法。当我不打开优化(-O0)时,程序可以正常运行。但是当我打开优化级别(-O1/2/3)时,程序无法终止。在Visual Studio下,debug模式和release模式都可以正常运行。以上情况,代码都是一样。我不知道怎么找到问题,谁能帮帮我?
class DstarLite {
public:
DstarLite() = delete;
DstarLite(GridStatus* a, GridStatus* b, FILE* fp)
: k_m_(0), start_(a), last_(start_), goal_(b), open_close_(fp) {}
void calculateKey(GridStatus* s);
void updateVertex(GridStatus* u);
void initialize();
void computeShortestPath();
void rePlanning(vector<pair<GridStatus*, int>>& node_change);
GridStatus* getStart();
void setStart(GridStatus* val);
GridStatus* getGoal();
private:
Fib frontier_;
double k_m_;
unordered_map<GridStatus*, handle_t>
heap_map_;
GridStatus* start_;
GridStatus* last_;
GridStatus* goal_;
FILE* open_close_;
};
void DstarLite::calculateKey(GridStatus* s) {
s->f = min(s->g, s->rhs) + heuristic(start_, s) + k_m_;
s->k2 = min(s->g, s->rhs);
}
void DstarLite::initialize() {
fprintf(open_close_, "%d %d\n", start_->x, start_->y);
fprintf(open_close_, "%d %d\n", goal_->x, goal_->y);
goal_->rhs = 0;
calculateKey(goal_);
handle_t hand = frontier_.push(goal_);
heap_map_[goal_] = hand;
}
void DstarLite::updateVertex(GridStatus* u) {
bool heap_in = heap_map_.find(u) != heap_map_.end();
if (u->g != u->rhs && heap_in) {
calculateKey(u);
frontier_.update(heap_map_[u]);
} else if (u->g != u->rhs && !heap_in) {
calculateKey(u);
handle_t hand = frontier_.push(u);
heap_map_[u] = hand;
} else if (u->g == u->rhs && heap_in) {
calculateKey(u);
frontier_.erase(heap_map_[u]);
heap_map_.erase(u);
}
}
void DstarLite::computeShortestPath() {
int count = 0;
while (smaller(frontier_.top(), start_) || !myEqual(start_->rhs, start_->g)) {
count++;
auto u = frontier_.top();
pair<double, double> k_old = {u->f, u->k2};
pair<double, double> k_new;
k_new.first = min(u->g, u->rhs) + heuristic(start_, u) + k_m_;
k_new.second = min(u->g, u->rhs);
if (k_old < k_new) {
calculateKey(u);
frontier_.update(heap_map_[u]);
} else if (myGreater(u->g, u->rhs)) {
u->g = u->rhs;
frontier_.pop();
heap_map_.erase(u);
for (auto s : neighbors(u)) {
if (s->rhs > u->g + cost(u, s)) {
s->next = u;
s->rhs = u->g + cost(u, s);
updateVertex(s);
}
}
} else {
double g_old = u->g;
u->g = kDoubleInfinity;
auto neighbor = neighbors(u);
neighbor.push_back(u);
for (auto s : neighbor) {
if (myEqual(s->rhs, cost(s, u) + g_old)) {
if (!equal(s, goal_)) {
double pp_s = kDoubleInfinity;
for (auto succ : neighbors(s)) {
double dis = succ->g + cost(succ, s);
if (dis < pp_s) {
pp_s = dis;
s->next = succ;
}
}
s->rhs = pp_s;
}
}
updateVertex(s);
}
}
}
cout << "Dstar visited nodes : " << count << endl;
}
void DstarLite::rePlanning(vector<pair<GridStatus*, int>>& node_change) {
k_m_ += heuristic(last_, start_);
last_ = start_;
for (auto change : node_change) {
GridStatus* u = change.first;
int old_threat = u->threat;
int new_threat = change.second;
double c_old;
double c_new;
u->threat = new_threat;
u->rhs += (new_threat - old_threat) * threat_factor;
updateVertex(u);
for (auto v : neighbors(u)) {
u->threat = old_threat;
c_old = cost(v, u);
u->threat = new_threat;
c_new = cost(v, u);
if (c_old > c_new) {
if (v != goal_) {
if (v->rhs > u->g + c_new) {
v->next = u;
v->rhs = u->g + c_new;
}
}
} else if (myEqual(v->rhs, c_old + u->g)) {
if (v != goal_) {
double pp_s = kDoubleInfinity;
for (auto pre : neighbors(v)) {
double dis = pre->g + cost(pre, v);
if (dis < pp_s) {
pp_s = dis;
v->next = pre;
}
}
v->rhs = pp_s;
}
}
updateVertex(v);
}
}
}
GridStatus* DstarLite::getStart() { return start_; }
void DstarLite::setStart(GridStatus* val) { start_ = val; }
GridStatus* DstarLite::getGoal() { return goal_; }
DstarLite dstar(start, goal, open_close);
dstar.initialize();
dstar.computeShortestPath();
抱歉,我觉得很难定位到代码中的问题,所以之前没有展示代码。现在重新编辑了题目,但是代码很多,主要调用部分是computeShortest().
由于您没有提供任何代码,我们只能给您一些一般提示来解决此类问题。
作为第一个假设,您的代码肯定存在一个或多个导致我们称之为 undefined behaviour UB 的错误。由于结果是未定义的,它可以是任何东西,并且经常随着不同的优化级别、编译器版本或平台改变行为。
你能做什么:
启用所有警告并修复它们!特别寻找诸如“比较总是...”、“使用 xxx(有时)未初始化”、“无效指针转换”之类的内容,...
尝试在不同的编译器上编译。您还应该尝试使用 gcc and/or clang,即使在 windows 上也是如此。第一次在 windows 平台上获取这些编译器 运行 的环境可能很难,但确实值得这样做。不同的编译器会给出不同的警告。修复来自所有编译器的所有警告是一个非常好的帮助!
你应该使用像
valgrind
这样的内存跟踪器。我对 windows 的经验不多,但我相信也有这样的工具,也许已经集成到您的开发套件中了。这些工具非常适合查找“of by x”访问、访问释放的内存等问题。如果您仍然运行遇到这样的麻烦,静态代码分析器工具可能会有所帮助。通常不像管理人员认为的那么多,因为今天的编译器通过检测恐龙程序员所期望的缺陷要好得多。额外的发现通常是误报,尤其是当您使用现代 C++ 时。通常,您可以省下这笔钱并参加 class 的教育!
评论,评论,与其他人一起评论!
把问题剪短!您应该将大部分开发时间花在设置良好的自动化单元测试上。检查每个路径,每个文件中的每个函数。很高兴看到至少 95% 的分支被测试覆盖。如果您更改优化器级别和/或编译器和平台,如果您的代码中有 UB,通常这些测试也会失败。
使用调试器可能会令人沮丧。在高度优化的代码中,您会跳过所有内容而什么都不会,您可能无法真正看到您在哪里以及与您的代码有什么关系。如果在较低的优化器级别中不存在错误,那么您实际上没有太多机会找到潜在的问题。
最后但同样重要的是:“printf 调试”。但这也可能会改变行为。在最坏的情况下,如果您添加调试输出,代码将始终 运行。但这是一个机会!
使用编译器中的线程和内存清理器。
问题是浮点数比较引起的。之前写代码的时候特意搁置了这个问题:)。修复后可以正常运行