Is there anything speaking against a structure like to following. In Release mode, Visual Studio seems to ignore i < 10 and execute the loop without end. If I set a break point I see that i runs from 0 to 9 and stays at 9 in all further iterations. If I printf i, I get a error after the 10 iteration, because arr only has 10 fields. Very strange. Please help.
for (i = 0; i < 10; i++){
switch (arr[i].type1){
case A:
//something
break;
case B:
switch (arr[i].type2){
//something
}
break;
default:
break;
}
}
Thanks!
EDIT: I removed all switch statements and replaced them with if statements. Work perfectly now. I still have difficulty believing that I was right and Visual Studio wrong. What about all my other Switch statements in the program? :/
I suspect that
// something
might have something to do with it. If you run this code as is (with the actual case code removed) -- does it happen?
How about if you take the entire switch and put it in a function?
You might be changing i somewhere in that // something either directly, or by some memory bounds issue.
nothing wrong with your example. Perhaps you have some accidental stack-overwriting or something like that in other parts of your code that introduce weird side effects in that place (and no sense making debugging sessions)?
Change the loop variable to j and make the first line of the loop:
int i = j;
Does it still do it?
As long as I don't know what // something does, I'll just give you the best idea I have given what I know;
If this only occurs in release mode, I would guess that the optimization done by the compiler may be the cause if this odd behaviour.
If you can make this occur reliably with the exact code given above, I'd say you should try turning off optimization and see if that helps.
Related
I have encounter a horrible situation.
I usually use visual code to edit my code, also compile and execute in it(F5).
But I found vscode is too smart or ignore some warning message for me. And
output the right answer, which also work fine in Ideone. But in window cmd or dev C++ my code can't output anything, just return a big number.
And I find some situation will occur the thing I mention above.
The code like this
for (i = 0; i < g.size(); i++)
{
int source;
int dest;
int minWeight = 999;
for (j = 0; i < g[j].size(); j++)
{
// no edge, come to next condition
if (!g[i][j])
continue;
if (g[i][j] < minWeight)
{
source = i;
dest = j;
minWeight = g[i][j];
}
}
if
updateGroup(index, index[source], index[dest]);
else
updateGroup(index, index[source], index[dest]);
}
You may found that the second for loops have wrong condition statement, it should change
j = 0; i < g[j].size(); j++ to j = 0; j < g[i].size(); j++
So I wonder to know
Are there any way let my vscode more strict?
Why it still can output right answer in vscode and ideone?
How to avoid or be easier to found where my code wrong when this kind of no message error?
Really hope someone can help me, and appreciate all of your suggestion!!
There is no way for the compiler or computer to read your mind and guess what you meant to write instead of what you really did mean.
Even when this mistake results in a bug, it cannot know that you did not intend to write this, or that you meant to write some other specific thing instead.
Even when this bug results in your program having undefined behaviour, it is not possible to detect many cases of undefined behaviour, and it is not worthwhile for a compiler author to attempt to write code to do this, because it's too hard and not useful enough. Even if they did, the compiler could still not guess what you meant instead.
Remember, loops like this don't have to check or increment the same variable that you declared in the preamble; that's just a common pattern (now superseded by the safer ranged-for statement). There's nothing inherently wrong with having a loop that increments i but checks j.
Ultimately, the solution to this problem is to write tests for your code, which is why many organisations have dedicated Quality Assurance teams to search for bugs, and why you should already be testing your code before committing it to your project.
Remember to concentrate and pay close attention and read your code, and eventually such typos will become less common in your work. Of course once in a while you will write a bug, and your tests will catch it. Sometimes your tests won't catch it, which is when your customers will eventually notice it and raise a complaint. Then, you release a new version that fixes the bug.
This is all totally normal software development practice. That's what makes it fun! 😊
1) Crank up your compiler warnings as high as they will go.
2) Use multiple different compilers (they all warn about different things).
3) Know the details of the language well (a multi year effort) and be really, really careful about the code you write.
4) Write (and regularly run) lots of tests.
5) Use tools like sanitizers, fuzzers, linters, static code analyzers etc. to help catch bugs.
6) Build and run your code on multiple platforms to keep it portable and find bugs exposed by different environments/implementations.
I'm a newbie in C++. As fas as I know, something like
switch(ival)
{
case 1,2,3:
/* do something */
/* other case selections */
}
is wrong. The correct way is to write:
switch(ival)
{
case 1: case 2: case 3: // in multiple lines if you prefer
/* do something */
/* other case selections */
}
That said (hoping it's correct), what happens when you compile the first? Visual Studio intellisense detects an error, but the program compiles fine.
I experimented a bit and I was betting that he would execute "do something" if ival was 1, but not if it was 2 or 3. I've setup multiple case statement like that, everyone with its own control variable to keep track of the execution, but nothing seems to happen as they all keep initialization values through the end of the program.
I'm puzzled. Anyone knows what happens behind the curtain?
When the compiler sees a case statement case N it will always interpret N as an integer. In this case, your compiler is evaluating the expression 1,2,3 as 3. Your /* do something */ code is only executed when ival is 3. (Tested with MSVS2015).
As you noted, this expression isn't the right way to express that you want multiple cases to be handled by the same code, and you should expect other compilers to handle the situation differently.
I have a program that behaves weirdly and probably has undefined behaviour. Sometimes, the return address of a function seems to be changed, and I don't know what's causing it.
The return address is always changed to the same address, an assertion inside a function the control shouldn't be able to reach. I've been able to stop the program with a debugger to see that when it's supposed to execute a return statement, it jumps straight to the line with the assertion instead.
This code approximates how my function works.
int foo(Vector t)
double sum = 0;
for(unsgined int i=0; i<t.size();++i){
sum += t[i];
}
double limit = bar(); // bar returns a value between 0 and 1
double a=0;
for(double i=0; i<10; i++){
a += f(i)/sum; // f(1)/sum + ... + f(10)/sum = 1.0f
if(a>3)return a;
}
//shoudn'get here
assert(false); // ... then this line is executed
}
This is what I've tried so far:
Switching all std::vector [] operators with .at to prevent accidentily writing into memory
Made sure all return-by-value values are const.
Switched on -Wall and -Werror and -pedantic-errors in gcc
Ran the program with valgrind
I get a couple of invalid read of size 8, but they seem to originate from qt, so I'm not sure what to make of it. Could this be the problem?
The error happens only occasionally when I have run the program for a while and give it certain input values, and more often in a release build than in a debug build.
EDIT:
So I managed to reproduce the problem in a console application (no qt loaded) I then manages to simulate events that caused the problem.
Like some of you suggested, it turns out I misjudged what was actually causing it to reach the assertion, probably due to my lack of experience with qt's debugger. The actual problem was a floating point error in the double i used as a loop condition.
I was implementing softmax, but exp(x) got rounded to zero with particular inputs.
Now, as I have solved the problem, I might rephrase it. Is there a method for checking problems like rounding errors automatically. I.e breaking on 0/0 for instance?
The short answer is:
The most portable way of determining if a floating-point exceptional condition has occurred is to use the floating-point exception facilities provided by C in fenv.h.
although, unfortunately, this is far from being perfect.
I suggest you to read both
https://www.securecoding.cert.org/confluence/display/seccode/FLP04-C.+Check+floating-point+inputs+for+exceptional+values
and
https://www.securecoding.cert.org/confluence/display/seccode/FLP03-C.+Detect+and+handle+floating-point+errors
which concisely address the exact question you are posing:
Is there a method for checking problems like rounding errors automatically.
I don't usually code C++, but a strange comp sci friend of mine got sick of looking at my wonderful FORTRAN programs and challenged me to rewrite one of them in C++, since he likes my C++ codes better. (We're betting money here.) Exact terms being that it needs to be compilable in a modern C++ compiler. Maybe he hates a good conio.h - I don't know.
Now I realize there are perfectly good ways of writing in C++, but I'm going for a personal win here by trying to make my C++ version as FORTRAN-esque as possible. For bonus points, this might save me some time and effort when I'm converting code.
SO! This brings me to the following related queries:
On gotos:
How do you work a goto?
What are the constraints on gotos in C++?
Any concerns about scope? (I'm going to try to globally scope as much as possible, but you never know.)
If I use the GCC extension to goto to a void pointer array, are there any new concerns about undefined behavior, etc?
On longjmp:
How would you safely use a longjmp?
What are the constraints on longjmps in C++?
What does it do to scope?
Are there any specific moments when it looks like a longjmp should be safe but in fact it isn't that I should watch out for?
How would I simulate a computed goto with longjmp?
Is there any tangible benefit to using longjmp over goto if I only have one function in my program?
Right now my main concern is making a computed goto work for this. It looks like I'll probably use the longjmp to make this work because a void pointer array isn't a part of the C++ standard but a GCC specific extension.
I'll bite and take the downvote.
I seriously doubt that your friend will find Fortran written in C++ any easier (which is effectively what you'll get if you use goto and longjmp significantly) to read and he might even find it harder to follow. The C++ language is rather different from Fortran and I really don't think you should attempt a straight conversion from Fortran to C++. It will just make the C++ harder to maintain and you might as well stay with your existing codebase.
goto: You set up a label (my_label:) and then use the goto command goto my_label; which will cause your program flow to execute at the statement following the goto. You can't jump past the initialization of a variable or between functions. You can't create an array of goto targets but you can create an array of object or function pointers to jump to.
longjmp: There is no reason to prefer longjmp over goto if you have only one function. But if you have only one function, again, you really aren't writing C++ and you'll be better off in the long run just maintaining your Fortran.
You'll get plenty of haterade about using goto at all. Normally I'd jump right on the bandwagon, but in this particular case it sounds more like code golf to me. So here you go.
Use goto to move the instruction pointer to a "label" in your code, which is a C++ identifier followed by a colon. Here's a simple example of a working program:
#include <iostream>
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
int i = 0;
step:
cout << "i = " << i;
++i;
if( i < 10 )
goto step;
}
In this case, step: is the label.
There are concerns about context.
You can only goto to a label within the current function.
If your goto skips the initialization of a variable, you may evoke Undefined Behavior (Code which will compile, but you can't say for sure what it will actually do.).
You cannot goto in to a try block or catch handler. However, you can goto out of a try block.
You "can goto" with pointers etc provided the other concerns are met. If the pointer in question is in-scope at the call site and in-scope at the branch site, no problem.
I think this reference has most of the information you are looking for.
goto
longjmp
computed goto --> switch
Really, they share a (common, but not universal) underling implementation as a jump table.
If I understand the original question, the question is actually an interesting one. Rewording the question (to what I think is an equivalent question): "How do you do a FORTRAN computed goto in C?"
First we need to know what a computed goto is: Here is a link to one explanation: http://h21007.www2.hp.com/portal/download/files/unprot/fortran/docs/lrm/lrm0124.htm.
An example of a computed GOTO is:
GO TO (12,24,36), INDEX
Where 12, 24, and 36 are statement numbers. (C language labels could serve as an equivalent, but is not the only thing that could be an equivalent.)
And where INDEX is a variable, but could be the result of a formula.
Here is one way (but not the only way) to do the same thing in C:
int SITU(int J, int K)
{
int raw_value = (J * 5) + K;
int index = (raw_value % 5) - 1;
return index;
}
int main(void)
{
int J = 5, K= 2;
// fortran computed goto statement: GO TO (320,330,340,350,360), SITU(J,K) + 1
switch (SITU(J,K) + 1)
{
case 0: // 320
// code statement 320 goes here
printf("Statement 320");
break;
case 1: // 330
// code statement 330 goes here
printf("Statement 330");
break;
case 2: // 340
// code statement 340 goes here
printf("Statement 340");
break;
case 3: // 350
// code statement 350 goes here
printf("Statement 350");
break;
case 4: // 360
// code statement 360 goes here
printf("Statement 360");
break;
}
printf("\nPress Enter\n");
getchar();
return 0;
}
In this particular example, we see that you do not need C gotos to implement a FORTRAN computed goto!
Longjmp can get you out of a signal handler which can be nice - and it'll add some confusion as it will not reset automatic (stack-based) variables in the function it long jumps to defined prior to the setjmp line. :)
There is a GCC extension called Labels as Values that will help you code golf, essentially giving you computed goto. You can generate the labels automatically, of course. You will probably need to do that since you can't know how many bytes of machine code each line will generate.
I looked for an answer for two days to this with no success. I've never come across this problem before so I'll try my best. Please bear with me.
I returned to a C++ project I created over a year ago, which at the time ran without problems. I came across this interesting and incredibly annoying problem the other day as I was trying to get the same program to run. The code was something like:
file.h
...
short id;
...
file.cc
id = 0;
while (id < some_large_number)
{
id = foo();
if (id == 2)
{
//do something
}
else if (id == 2900)
{
//do something
}
else if (id == 30000)
{
//do something
}
else if (id == 40000)
{
//do something
}
else if (id == 45000)
{
//do something
}
else
{
//do something else
}
}
The constant numbers were macros in hex notation that I expanded for this example. Turns out that this was truly a bug, but the debugger did not make it easy to discover. Heres what happened:
As I was trying to step through the code using GDB (with no optimizations), I noticed that GDB would jump straight to the else statement after reaching if (id == 30000), everytime. Because the numbers were c macros in hex notation, I did not notice at first that 40000 was beyond the limit of a signed short. This was very misleading, and spent hours trying to figure it out: I recompiled external libraries, reinstalled g++, among other things.
Obviously, making id an unsigned short fixed the problem. The other problem seems like a compiler issue. But I still don't understand, why were those sections of code completely skipped during execution, and with no optimizations? Why would it not go through each if statement and that way I could identify the real problem? Any ideas?
Thanks so much. I hope this is okay for a first question.
If you enable all the warnings from gcc, it will tell you at compile time that this is going to happen.
short is 16 bits long and its range is -32768 to 32767. So it can never be 40000 or 45000 and compiler eliminated dead code (as it will never be reached).
GCC is an excellent optimizing compiler, however even when error and warning information is enabled via -Werror, -Wall, etc GCC still doesn't produce the same level of information a diagnostic compile does. While developing the code I would recommend using Clang, a diagnostic compiler, to help in finding bugs and error. Clang is intended to compatible with GCC, and with the exception of some more esoteric features I have had no problem changing my CC between the two in my Makefile.
Being an optimizing compiler, I believe GCC by default enable dead-code elimination. This would cause all branches which the compiler detected impossible, such as those outside the bounds of your id variable, to be eliminated. You might be able to disable that type of dead-code elimination.
Recall that during compiling, the C++ compiler looks through the code and determines what parts of the code execute in what order. If the compiler determines that a part of the code is never going to run, it will not optimize it.
For example:
int i = 0;
if( i == 1) {
printf("This will never be printed\n");
}
Here, there is no reason to optimize the if-statement, as it will never execute.
This sort of instance would be picked up if you compile with:
g++ -Wall mycode.c
where -Wall means show all warnings, and mycode.c is your project file.
As for execution, stepping through GDB shows the current flow of the program. If a branch (in an if-statement) is false, why would it ever go through that section of the code? You can only take one branch in an if-elseif-else statement.
I hope that helps you out.
My conclusion is the same as yours: It seems like it was optimized out even without "optimizations" turned on. Maybe these constant predicates "always true"/"always false" are used to skip the code somewhere directly in the code generation step, i.e. way sooner than any -O switch optimizations are being performed. Just a guess.