if (condition a) {
return (result b)
} else {
return (result c)
}
once I delete " }else{ } the code become
if (condition a) {
return (result b)
}
return (result c)
why the second code still make the same function as the first?
For me, in the second one, it will anyway runs the return (result c) however, it's not the case!
Any clarification?
Consider what happens in each example...
In the first example:
If condition a is true then the code inside that block will be executed, returning result b and exiting the function.
If the condition is not true, then the code inside the else block will be executed, returning result c and exiting the function.
In the second example:
If condition a is true then the code inside that block will be executed, returning result b and exiting the function.
If the condition is not true, then control will continue past the if block and execute the next code, returning result c and exiting the function.
Logically the two are the same. In this specific case, including the else is just a matter of personal preference.
For me, in the second one, it will anyway runs the return (result c)
Not if the function has already returned a result and exited. Then remaining code in the function is not executed, because it's already returned.
In most languages return (something) does two things:
define the return value of the current function/method/...
end the control flow of the current function/method/... and return to the caller.
It's the item #2 that means that even without the else the two pieces of code do essentially the same thing:
Since the code block warded by the if statement never completes normally, but instead returns to the caller the code after it will not be executed, when the if block is executed.
Related
Why if I have two conditions while both returns the right type in a function as it should be, I am getting an alarm.
control reaches end of non-void function [-Wreturn-type]
bool EtherTrafGen::isGenerator()
{
if (multipacket) return par("destAddresses").stringValue()[0];
else if (!multipacket) return par("destAddress").stringValue()[0];
}
What is the way to correct such an alarm?
Even though control can never reach
bool EtherTrafGen::isGenerator()
{
if (multipacket) return par("destAddresses").stringValue()[0];
else if (!multipacket) return par("destAddress").stringValue()[0];
//here
}
The compiler can't know that (since it's an else if) and it warns you about potential undefined behaviour if it is reached (maybe another thread modifies multipacket after the first check etc). You can just add a default return value to satisfy the compiler:
bool EtherTrafGen::isGenerator()
{
if (multipacket) return par("destAddresses").stringValue()[0];
else if (!multipacket) return par("destAddress").stringValue()[0];
return false;
}
Or just cut the whole else if since it's either true or false:
bool EtherTrafGen::isGenerator()
{
if (multipacket) return par("destAddresses").stringValue()[0];
return par("destAddress").stringValue()[0]; // multipacket must be false here anyway
}
You are missing one case:
bool EtherTrafGen::isGenerator()
{
if (multipacket) return par("destAddresses").stringValue()[0];
else {
if (!multipacket) return par("destAddress").stringValue()[0];
else ???? <---- what should be done here
}
}
I'll start by saying that the way you've structured your condition is quite exotic. You should just write it as:
if (multipacket) doX()
else doY()
It is true that the compiler should be smart enough to figure this case out, and not print an error.
However, your compiler isn't that smart. It's better not to have the warning, than to have it and know you're right.
Looking more broadly, there is a possibility that the code above is wrong, and it's not just the case that the compiler is not powerful enough in its analysis.
If the following code occurs in a multithreaded context, you might have rare threading issues where on the first access to multipacket you read a false, thus forcing you go to the second branch, and on the second access you read a true, thus forcing you go go out of the function without any return value. This case might happen if another thread modifies multipacket in between the two times it is read.
Granted, it's a small chance, as even if multipacket is changed by a separate thread, the modification might not be visible in that method immediately, because the value is in a register/cache/other temporary location that has been introduced by the compiler.
But why take the chance and write un-idiomatic code and have a warning on your hands?
In my program I was trying to update a value from multiple threads. I know how to use mutex (pthread_mutex_lock(), pthread_mutex_unlock()) to do this, but I just learned about gcc atomic builtins so I would like to have a try.
shared value A;
void each_working_thread() {
thread local variable B;
if (is_valid(A,B))
__sync_sub_and_fetch(A,B);
else
throw error;
}
where is_valid() is a const function that return boolean.
Is this correct, or the value of A could be updated by another thread during is_valid() ?
I assume is_valid(A, B) can change depending on A.
In which case, this is not safe - consider the following sequence:
Thread 1 calls is_valid(A, B) and gets true
Thread 2 calls is_valid(A, B) and gets true
Thread 1 calls __sync_sub_and_fetch(A, B) changes A, and the new value of A means is_valid(A, B) is now false.
Thread 2 calls __sync_sub_and_fetch(A, B) even though it shouldn't because is_valid(A, B) is now false.
You may be interested in the compare-exchange operation. In this case you can write something like:
int oldValueOfA, newValueOfA;
do {
oldValueOfA = A;
__sync_synchronize(); // memory barrier; makes sure A doesn't get accessed after this line
if (!is_valid(oldValueOfA, B))
throw error;
newValueOfA = oldValueOfA - B;
} while(!__sync_bool_compare_and_swap(&A, oldValueOfA, newValueOfA));
You can't make the two operations atomic, but you can detect if they weren't atomic and then you can try again.
This works because if A doesn't still contain oldValueOfA, __sync_bool_compare_and_swap does nothing and returns false. Otherwise, it sets it to newValueOfA and returns true. So if it returns true, you know nobody else changed A while you were busy calling is_valid. And if it returns false, then you haven't actually done anything yet, so you're free to go back and try again.
Note that is_valid might be called several times; this is relevant if it has side effects (like printing a message on the screen). In that case you should just use a mutex.
That probably is not thread safe, depending on what exactly is_valid does.
The point of that specific builtin is just to perform an atomic subtraction.
Consider this code
A = A - B;
This is not thread safe because it requires at least 2 atomic steps - the A - B, and then the assignment back to A. The builtin for this solves that one scenario.
I could understand that it is iterating the buckets_ , but what is the action in this for loop? In my debugging, if (it->second) is satisfied if (this->next()->putq(it->second) == -1) is not satisfied. So does this for-loop could only judge if the GADGET fail or not?
for (map_type_::iterator it = buckets_.begin(); it != buckets_.end(); it++) {
if (it->second) {
if (this->next()->putq(it->second) == -1) {
it->second->release();
GDEBUG("Failed to pass bucket down the chain\n");
return GADGET_FAIL;
}
}
}
Your map most likely contains pointers. if (it->second) checks if the pointer is NULL or not, if not NULL, execution goes to next if statement (if (this->next()->putq(it->second) == -1)) most likely to "pass the bucket down the chain"...if this fails (returns -1), then GADGET_FAIL is returned as an erreor code.
It is possible that putq actually never returns -1, or, possibly only in very critical situations (system running out of memory for instance). So it's possible that the code inside the second if statement is (almost) impossible to reach.
So, the loop can judge if the GADGET "passing down the chain" failed or not. But it probably never fails.
That's all that can be said without more code of putq posted...
I have a couple of if statements in my C++ code (one nested inside the other), and I want to be sure that they will run as I expect- the code is:
if(state == entry){
if(abs(distance < 0.05){
state = arcing;
...
startAngle = positionAC;
}
// Some more statements here...
}
If the second if statement condition is met, will the code where my comment "// Some more statements here..." be run now that the value of state has changed to arcing rather than entry? I would have thought that they should be run because the code will still be executing from when the first condition was true, even though it now no longer will be. Is this correct?
The if-check
if(state == entry)
will be performed exactly once, at the moment that line is reached in the code.
From then on, it doesn't matter if the values of state or entry are modified - the entirety of the code inside the if-block will be executed, if state was equal to entry when that line was reached.
Yes. I remember once having this doubt about the Pascal while loop. The text book we had didn't describe the workings of the loop in very concrete terms, but only that it iterated “while” the condition was true. Some experimentation convinced me that the condition was only checked once per iteration, namely at the start of the loop. But the thing is, I should not have had to check that: the book should have been clear on that.
So, clarity:
A C++ if statement like
if( condition )
{
action_1;
action_2;
action_3;
}
something_more;
is 1equivalent to:
const bool do_it = condition; // The single evaluation of condition
if( do_it ) goto do_actions;
goto do_more_things;
do_actions: // Just a name for this place in the code, a "label".
action_1;
action_2;
action_3; // The next executed statement is something_more.
do_more_things:
something_more;
And yes, both are valid C++ code.
1) This equivalence ignores possible name collisions, and it assumes that none of the actions are declarations. Declarations can foil the equivalence in two ways. First, it's not permitted to goto-jump over a declaration that executes initialization and that's in scope at the point jumped to. Second, destructors are executed when the execution leaves a block, and to capture that one has to imagine that those destructor executions are among the actions.
If the condition in the if statement
if(state == entry){
will be evaluated to true (it is evaluated only once in this point) then the compound statement of the if will be executed.
The statements under the comment will be executed exactly once, unless the first condition itself is NOT within a loop, or a method which is called recursively.
But if you want to make sure that the code after the comment is executed only when the state == entry at that point of time you can change your code as below
if((state == entry) && (abs(distance < 0.05)) {
state = arcing;
...
startAngle = positionAC;
}
else if (state == entry)
{
// Some more statements here...
}
I have a weird problem:
On my Win32 C++ App, I have a function where the function returns after a call to another function.
void f()
{
//SECTION 1//
if( interactFrame )
{
psFrame->getWindow()->deactivate();
interactFrame = activeFrame = 0;
logFile << "PS deactive" << endl;
}
//SECTION 2//
}
void Window::deactivate()
{
SetLayeredWindowAttributes( handle_, 0, 0, LWA_ALPHA );
SetFocus( applicationWindow_ );
}
After I call f(), the function goes through Section 1, branches into the if statement, completes line 1 (psFrame->...) and returns after that without evaluating the remaining two lines and the Section 2 out of the branch. I had this happen to me when for instance I was calling a method of a variable which was NULL, in this case psFrame, and it would instead of breaking, just return. However it is a legitimate variable, its contents and the pointer returned from getWindow() exists. In fact I can trace until the completion of deactivate() however my breakpoint at the next line is never hit.
In fact this is the same code that runs on one computer, and doesn't on my laptop. Both running Win 7.
What do you think could be the cause of this?
It sounds like something (quite possibly the deactivate, or something it calls) is making a mess of the stack (e.g., overwriting the end of a buffer) and messing up the return address. Much more than that would be a pretty wild guess though.
Given your description, it still sounds like you are getting null dereference errors. Guard your code a bit and see what happens like this:
if( interactFrame )
{
if (psFrame)
{
if (psFrame->getWindow())
{
psFrame->getWindow()->deactivate();
}
// else log("getWindow == null")
}
// else log("psFrame == null")
interactFrame = activeFrame = 0;
logFile << "PS deactive" << endl;
}
Beyond that we'd need to see more code.
UPDATE: OK - you posted more code, and that's pretty odd, unless something very strange is happening like getWindow() is overrunning your stack and trashing the return address. Check any local variables (especially strings and arrays) you have in getWindow().
GMan also has a good point - if psFrame is returning a pointer to a deleted window in getWindow, that could also be a culprit (and you might see different behaviors depending on if the memory has been re-allocated or not yet)
I guess the line
psFrame->getWindow()->deactivate();
simply generates an exception. And your function does not return at all - it terminates with exception. To confirm that set a breakpoint after the call to f() function (part of which is the code you've posted) and if this breakpoint doesn't hit either then it is likely an exception (possibly invalid memory access or simply C++ exception thrown).
Stack corruption is also possible and it will also likely lead to an exception (unless you accidentally overwrite return address with a valid address to executable memory).
Also note that if psFrame happen to be 0 (or other invalid pointer) then exception is guaranteed if getWindow() access any non-static member of its object in any way. And you would see exactly the behaviour you described. The same situation is when psFrame->getWindow() returns 0 (or another invalid pointer) and deactivate() accesses non-static member.
UPD:
You may also follow stack contents changes when debugging.