Why does this if/else statement appear to be optimized away? - c++

This is the code in question:
void DeckTug::StickCallback(unsigned long long evtID, DWORD value)
{
long int val = value;
if (evtID == stickXInputID || evtID == stickAxisXInputID)
stickXpct = (((double)val)) / 325.94;
else if (evtID == stickYInputID || evtID == stickAxisYInputID) {
stickYpct = (((double)val)) / 325.94;
if(isAuto)
if ((stickYpct < 0.0)) {
acPullingTug = true;
tugTBoffset = tugReversed ? towbarAttachAft * (-1.0) : towbarAttachForward;
}
else {
acPullingTug = false;
tugTBoffset = tugReversed ? towbarAttachAft * (-1.0) : towbarAttachForward;
}
}
}
When I compile a debug build, this runs perfectly. When I compile a release build, it does not work. When I attach the visual studio debugger to the release version, I can break on the first if statement and on the closing brace of the function, but I cannot hit a break point anywhere else, and neither stickXpct or stickYpct are ever being assigned anything, although in the debugger I can see that "value" has a valid value, and "evtID" DOES equal one of inputIDs.
In conclusion, it looks to me like, in the release version of the code only, both the first "if" statement and the first "else if" statement only evaluate to false, even when one of them should evaluate to true. Does anyone know what is going on here? because I don't.
Thanks so much,
Farley

Edit: changed answer in response to comments
Try adding volatility
void DeckTug::StickCallback(unsigned long long evtID, DWORD value)
{
long int val = value;
volatile unsigned long long _evtID = evtID;
if (_evtID == stickXInputID || _evtID == stickAxisXInputID)
stickXpct = (((double)val)) / 325.94;
else if (_evtID == stickYInputID || _evtID == stickAxisYInputID) {
stickYpct = (((double)val)) / 325.94;
if(isAuto)
if ((stickYpct < 0.0)) {
acPullingTug = true;
tugTBoffset = tugReversed ? towbarAttachAft * (-1.0) : towbarAttachForward;
}
else {
acPullingTug = false;
tugTBoffset = tugReversed ? towbarAttachAft * (-1.0) : towbarAttachForward;
}
}
}
That should prevent the compiler from optimizing those branches until you can track down why it wants to optimize those branches away.

Related

If else ladder optimisation

if (value >= 2) {
return 1
} else if (value >= 1) {
return 0.9;
} else if (value >= 0.8) {
return 0.7
} else if (value >= 0.5) {
return 0.5;
} else {
return 0;
}
How to solve this if-else ladder. If i use switch cyclometric complexity increases and also also values feels like true.
In some cases the solution is breakaway code. Not everyone likes it - I do like it.
It just means you handle situations "from the top" and end situations with a return
pseudocode in any language...
(Everything should be in a function anyway...)
HandleTemperature(float t)
{
if (t > 90)
{
RunEmergencyCooling();
return;
}
if (round.t == 63)
{
DealWithgMagicValue();
return;
}
if (round.t > 40)
{
Debug.("normal temps! no worries!);
return;
}
// if you get to here, temp is very lopw
RunEmergencyHeating();
}
(In many languages there's a "finally" or "always do" concept, which can work well w/. breakaway dcode.)
Your example ...
Step 1, put in in a function as it should be anyway, Step 2 use "breakaway chunks".
float HandleValue(float v)
{
if (2.0 <= v) {
return 1
}
if (0.7 < v && v < 2.0) {
return 0.9;
}
if (0.13 <= v && v <= 0.7) {
return 17.6;
}
log didn't find a bracket in HandleValue
return default value
}
Every bracket is totally explicit. You can easily build testing code from there, too.
Those annoying long blocks before errors ...
Breakaway is particularly clean-looking in error cases...
Something()
{
if comms.text != 17.2
{
.. 100s of lines of code here ..
.. they are all indented ..
}
else
{
an error!
}
}
Some (but not all) believe this is better:
Something()
{
if comms.text == 17.2
{
an error!
return; .. note the "return" in breakaway code
}
.. 100s of lines of code here ..
.. no need for indentation ..
}
"Breakaway code" may work for you in some cases; in any event you can be aware of the approach.

g++ optimization makes the program unable to run

I implemented a path planning algorithm based on D*-Lite. When I do not turn on optimization (-O0), the program can run normally. But when I turn on the optimization level (-O1/2/3), the program cannot be terminated. In Visual Studio, both debug mode and release mode can run normally. In the above cases, the codes are the same.I don’t know how to find the problem, can anyone help me?
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();
Sorry, I think it is difficult to locate the problem in the code, so the code was not shown before. Now I have re-edited the question, but there are a lot of codes, and the main calling part is computeShortest().
As you did not provide any code, we can give you only some general hints to fix such problems.
As a first assumption your code has definitely one or more bugs which causes what we call undefined behaviour UB. As the result is undefined, it can be anything and is often changing behaviour with different optimization levels, compiler versions or platforms.
What you can do:
enable really ALL warnings and fix them all! Look especially for something like "comparison is always...", "use of xxx (sometimes) without initialization", " invalid pointer cast", ...
try to compile on different compilers. You should also try to use gcc and/or clang, even on windows. It is maybe hard in the first time to get the environment for these compilers run on windows plattforms, but it is really worth to do it. Different compilers will give different warnings. Fixing all warnings from all compilers is a really good help!
you should use memory tracers like valgrind. I have not much experience on windows, but I believe there are also such tools, maybe already integrated in your development suite. These tools are really good in finding "of by x" access, access freed memory and such problems.
if you still run into such trouble, static code analyser tools may help. Typically not as much as managers believe, because today's compilers are much better by detecting flaws as expected by dinosaur programmers. The additional findings are often false positives, especially if you use modern C++. Typically you can save the money and take a class for your own education!
Review, Review, Review with other people!
snip the problem small! You should spend most of your development time by setting up good automated unit tests. Check every path, every function in every file. It is good to see at minimum 95% of all branches covered by tests. Typically these tests will also fail if you have UB in your code if you change optimizer levels and or compiler and platforms.
using a debugger can be frustrating. In high optimized code you jump through all and nothing and you may not really see where you are and what is the relation to your code. And if in lower optimizer level the bug is not present, you have not really much chance to see find the underlying problem.
last but not least: "printf debugging". But this may change the behaviour also. In worst case the code will run always if you add a debug output. But it is a chance!
use thread and memory sanitizers from your compiler.
The problem is caused by the comparison of floating-point numbers. I deliberately put aside this question when I wrote the code before :). Now it can operate normally after being fixed.

How to make a switch to true and false?

I want to learn how to make compact switches, tell me if I'm doing it right or can I simplify it?
auto _time = 5s;
bool save_time;
auto fs_time = steady_clock::now();
for(;;) {
auto now_time = steady_clock::now();
if (duration_cast<seconds>(now_time - fs_time) >= _time) {
save_time = true;
}
else {
save_time = false;
}
// CODE ....
if(save_time) {
// CODE ....
}
if(save_time) {
// CODE 2 ....
}
}
I do this to not write the same thing repeatedly.
if (duration_cast<seconds>(now_time - fs_time) >= _time) {}
Perhaps this slows down the code when it checks it constantly.
Compact means in one line?
save_time = (duration_cast<std::chrono::seconds>(now_time - fs_time) >= _time) ? true : false;
Or even more compact as Default suggested:
save_time = (duration_cast<std::chrono::seconds>(now_time - fs_time) >= _time);
Regarding the use of using, have a look to this question: Why is "using namespace std;" considered bad practice?

What's a graceful way of doing an "if none of the above"?

I'm sure you've been there. You want to say "if flib do this, if flob do that, if flab do diet, etc" where any number of them can be true, then at the end you want an "if you didn't do ANY of them".
For example (the examples below are in Swift, as I've been playing with it, but I think the situation is the same in most languages):
let thing = 101
var isInteresting = false
if (thing % 3 == 0) {
println("\"\(thing)\" is a multiple of three.")
isInteresting = true
}
if (thing > 100) {
println("\"\(thing)\" is greater than one hundred.")
isInteresting = true
}
if (thing > 1000) {
println("\"\(thing)\" is greater than one thousand.")
isInteresting = true
}
if !isInteresting {
println("\"\(thing)\" is boring.")
}
I find keeping track of a boolean to tell me whether I did anything or not kinda ungainly.
The only other way I came up with was this:
let thing = 101
let isAMultipleOfThree = (thing % 3 == 0)
let isGreaterThan100 = (thing > 100)
let isGreaterThan1000 = (thing > 1000)
if isAMultipleOfThree {
println("\"\(thing)\" is a multiple of three.")
}
if isGreaterThan100 {
println("\"\(thing)\" is greater than one hundred.")
}
if isGreaterThan1000 {
println("\"\(thing)\" is greater than one thousand.")
}
if !(isAMultipleOfThree || isGreaterThan100 || isGreaterThan1000 ) {
println("\"\(thing)\" is boring.")
}
but if anything that's worse (if you add a new clause you need to remember to add it in three places.
So my question is, is there a neat, succinct way of doing this?
I'm dreaming of an imaginary switch-like statement:
switchif { //Would have fallthrough where every case condition is checked
case thing % 3 == 0:
println("\"\(thing)\" is a multiple of three.")
case thing >100 :
println("\"\(thing)\" is greater than one hundred.")
case thing > 1000:
println("\"\(thing)\" is greater than one thousand.")
none: //Unlike 'default' this would only occur if none of the above did
println("\"\(thing)\" is boring.")
}
It's a good question that does not have a perfect answer. However, here's one other idea in addition to those you suggest: Encapsulate the testing machinery in a procedure to allow the calling code at least to be a bit more streamlined.
Specifically, for your example, the calling code can be this:
if (! doInterestingStuff(101)) {
println("\"\(thing)\" is boring.");
}
If testing is encapsulated into a procedure:
public boolean doInterestingStuff(int thing) {
var isInteresting = false
if (thing % 3 == 0) {
println("\"\(thing)\" is a multiple of three.")
isInteresting = true
}
if (thing > 100) {
println("\"\(thing)\" is greater than one hundred.")
isInteresting = true
}
if (thing > 1000) {
println("\"\(thing)\" is greater than one thousand.")
isInteresting = true
}
return isInteresting
}
I'm not sure how you'd do this in Swift, but since you didn't give a language tag I'll answer in C++.
The key to this is that && is short circuiting, and the second part won't be evaluated when the first part is false. It's the same idea as your boolean flag, but it's a little more automated.
struct Tracker
{
Tracker() : any(false) { }
bool operator()() { any = true; return true; }
bool any;
};
int thing = 101;
Tracker tracker;
if (thing % 3 == 0 && tracker()) {
printf("\"%d\" is a multiple of three.\n", thing);
}
if (thing > 100 && tracker()) {
printf("\"%d\" is greater than one hundred.\n", thing);
}
if (thing > 1000 && tracker()) {
printf("\"%d\" is greater than one thousand.\n", thing);
}
if (!tracker.any) {
printf("\"%d\" is boring.\n", thing);
}
See it in action: http://ideone.com/6MQYY2
kjhughes' answer inspired me a little:
Perhaps one could write a global function that accepts an indeterminate number of key-value pairs (or even just two element arrays), where the key is a comparison and the value is the statement to run if it's true. Then return false if none of them were run, otherwise true.
Update:
Tried it, it's horrible!
//Function:
func ifNone(ifNoneFunc:()->Void, tests: Bool...)
{
var oneTestPassed = false
for test in tests
{
oneTestPassed |= test
}
if(!oneTestPassed)
{
ifNoneFunc()
}
}
//Example:
let thisThing = 7
ifNone(
{
println("\(thisThing) is boring")
},
{
if(thisThing % 10 == 0)
{
println("\"\(thisThing)\" is a multiple of 10")
return true
}
else
{
return false
}
}(),
{
if(thisThing % 3 == 0)
{
println("\"\(thisThing)\" is a multiple of 3")
return true
}
else
{
return false
}
}(),
{
if(thisThing > 1_000_000)
{
println("\"\(thisThing)\" is over a million!!")
return true
}
else
{
return false
}
}()
)

Breaking out of if statement

I am writing a program in which I use an if statement to check some condition; if true I increment a counter. The problem is that as soon as the statement is true the variable either gets incremented endlessly or by random number.
I have been trying to use some clause to break out of this statement if condition meet but with no luck
my code:
if(res_vect_angle >=60 && res_vect_angle <=100 && left_mag_b >100)
{
//line(drawing, *iter_s, *(iter_s -1), Scalar( 255, 255, 255 ), 2,8 );
left_hook_count++;
cout<<"Left Hook:..........................!!! "<<left_hook_count<<endl;
if(left_hook_count++ == true)
{
break;
}
}
The whole chunk of code associated with the issue:
float M1, M2;
float A1, A2;
double left_mag_a, left_mag_b;
double res_vect_angle;
int i = 0;
for(vector<Point>::iterator iter_lh = Leftarm.begin(); iter_lh != Leftarm.end(); ++iter_lh)
{
if(iter_lh->y <=240 && iter_lh->y >=60 && iter_lh->x >=340 && iter_lh->x <=680)
{
left_detect.push_back(*iter_lh);
if(i % 4 == 0)
{
if(left_detect.size()>4)
{
for(vector<Point>::iterator iter_s = left_detect.begin()+3; iter_s != left_detect.end(); ++iter_s, i++)
{
//Resultant Magnetude
M1 = pow((double) iter_s->x + (iter_s -2)->x,2);
M2 = pow((double) iter_s->y + (iter_s -2)->y,2);
left_mag_a = (M1 + M2);
left_mag_b = sqrt(left_mag_a);
//Resultant Angle
A1 = abs(iter_s->x - (iter_s -2)->x);
A2 = abs(iter_s->y - (iter_s -2)->y);
res_vect_angle = abs(atan2(A1,A2) * 180 /PI);
//cout<<"LEFT HOOK ANGLE IS: "<<res_vect_angle<<endl;
if(res_vect_angle >=60 && res_vect_angle <=100 && left_mag_b >100)
{
//line(drawing, *iter_s, *(iter_s -1), Scalar( 255, 255, 255 ), 2,8 );
left_hook_count++;
cout<<"Left Hook:..........................!!! "<<left_hook_count<<endl;
if(left_hook_count++ == true)
{
break;
}
}
}
}
}
}
}
Hope this helps guys ps. left_hook_count++; is a int variable declared on top of my main().
The best solution is probably to invert the test, and make all the rest of the outer if conditional:
if (whatever) {
// do some stuff
if (left_hook_count != true) { // or whatever the test should really be
// do some more stuff
}
}
You could get the program flow you want using goto with a label after the outer if, but you don't want to.
On the other hand, it sounds like perhaps this is in a loop, and you don't want to enter the if block at all if the counter has been incremented? In that case you want:
if (left_hook_count == 0 && whatever) {
// do some stuff
}
you could provide more details so that we can figure out whats happening.
You might not have initialized it?
and checking again
if(left_hook_count++ == true)
it will increment it again unneccessariy and for for first count (0 : it wont happen)
i guess you 're using some recursive function. so check for Break condition (all test cases too).
Don't compare left_hook_count++ to true. In this context, true is equal to 1, and once left_hook_count exceeds 1, this test will fail and the code will never hit the break.
And you don't break out of an if statement. You break out of a loop; a break in an if statement inside the loop is one way of doing this.
You can just negate the condition, instead of trying to break out of the if:
if(...) {
if(!left_hook_count++) {
// Do what you need to do
}
}
my new answer:
:mylabel if (some_condition)
{
//code
if (some_condition) {break mylabel;}
//code
}
my old answer: Replace the if statement with a while statement containing a unconditional break at the end.
(old answer was before I learned of attaching labels to statement blocks.)
In your case:
while(res_vect_angle >=60 && res_vect_angle <=100 && left_mag_b >100)
{
//line(drawing, *iter_s, *(iter_s -1), Scalar( 255, 255, 255 ), 2,8 );
left_hook_count++;
cout<<"Left Hook:..........................!!! "<<left_hook_count<<endl;
if(left_hook_count++ == true)
{
break;
}
break; //this unconditional break makes the while loop act as an if statement
}
However if you don't have code after the conditional break what's the point of having it? I'm assuming you've omitted that code? The way you wrote it it would simply break out of the inner for loop.