D * -Lite를 기반으로 경로 계획 알고리즘을 구현했습니다. 최적화 (-O0)를 설정하지 않으면 프로그램이 정상적으로 실행될 수 있습니다. 하지만 최적화 수준 (-O1 / 2 / 3)을 켜면 프로그램을 종료 할 수 없습니다. 에서 Visual Studio를 모두 디버그 모드와 릴리즈 모드는 일반적으로 실행할 수 있습니다. 위의 경우 코드는 동일합니다 . 문제를 찾는 방법을 모르겠습니다. 누구든지 도와 줄 수 있습니까?
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 () 입니다.
코드를 제공하지 않았으므로 이러한 문제를 해결하기위한 일반적인 힌트 만 제공 할 수 있습니다.
첫 번째 가정으로 코드에는 정의되지 않은 동작 UB 라고 부르는 원인이되는 버그가 하나 이상 있습니다 . 결과가 정의되지 않았기 때문에 그것은 무엇이든 될 수 있으며 종종 다른 최적화 수준, 컴파일러 버전 또는 플랫폼으로 동작을 변경합니다.
할 수있는 일 :
실제로 모든 경고를 활성화하고 모두 수정하십시오! 특히 "비교는 항상 ...", "초기화없이 xxx (때때로) 사용", "잘못된 포인터 캐스트", ...
다른 컴파일러에서 컴파일을 시도하십시오. Windows에서도 gcc 및 / 또는 clang을 사용해야합니다. 처음에는 이러한 컴파일러를위한 환경을 Windows 플랫폼에서 실행하는 것이 어려울 수 있지만 실제로 수행 할 가치가 있습니다. 다른 컴파일러는 다른 경고를 제공합니다. 모든 컴파일러의 모든 경고를 수정하는 것은 정말 좋은 도움이됩니다!
같은 메모리 추적 프로그램을 사용해야합니다 valgrind
. Windows에 대한 경험은 많지 않지만 이미 개발 제품군에 통합 된 이러한 도구도 있다고 생각합니다. 이러한 도구는 "x 별"액세스, 해제 된 메모리 액세스 및 이러한 문제를 찾는 데 정말 좋습니다.
여전히 이러한 문제가 발생하면 정적 코드 분석기 도구가 도움이 될 수 있습니다. 일반적으로 관리자가 생각하는 것만 큼은 아닙니다. 오늘날의 컴파일러는 공룡 프로그래머가 예상 한대로 결함을 감지함으로써 훨씬 더 낫기 때문입니다. 특히 최신 C ++를 사용하는 경우 추가 결과는 종종 오탐입니다. 일반적으로 돈을 절약하고 자신의 교육을위한 수업을들을 수 있습니다!
다른 사람들과 함께 검토, 검토, 검토하십시오!
문제를 작게 잘라내세요! 좋은 자동화 된 단위 테스트를 설정하여 대부분의 개발 시간을 소비해야합니다. 모든 파일의 모든 경로, 모든 기능을 확인하십시오. 테스트에 포함 된 모든 분기의 최소 95 %를 확인하는 것이 좋습니다. 일반적으로 이러한 테스트는 최적화 수준이나 컴파일러 및 플랫폼을 변경하면 코드에 UB가있는 경우에도 실패합니다.
디버거를 사용하면 실망 스러울 수 있습니다. 고도로 최적화 된 코드에서는 모든 것을 건너 뛰고 아무것도하지 않고 현재 위치와 코드와의 관계를 실제로 보지 못할 수 있습니다. 그리고 낮은 최적화 수준에서 버그가 존재하지 않으면 근본적인 문제를 찾을 기회가별로 없습니다.
마지막으로 중요한 것은 "printf 디버깅"입니다. 그러나 이것은 또한 행동을 바꿀 수 있습니다. 최악의 경우 디버그 출력을 추가하면 코드가 항상 실행됩니다. 하지만 기회입니다!
컴파일러의 스레드 및 메모리 새니 타이 저를 사용하십시오.
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다