I set a breakpoint inside a conditional statement that checks for a certain value of a custom datatype. The game will break, but the line it breaks on is completely outside of my breakpoint's scope. Watch variables reveal that it just breaks the first time that loop is iterated through, rendering my debugging conditional statement absolutely useless.
In Visual Studio, the debugger would respect scope, and placing a breakpoint inside a conditional statement would only stop the game if that conditional evaluated to true. Why is this not the case with the GDB debugger in CodeBlocks? Is it because I'm using GDB in Windows? Here's the code:
for(int j = 0 ; j < r->components[i].size() ; j++)
{
itype_id type = r->components[i][j].type;
int req = r->components[i][j].count;
//DEBUGGING ONLY!!!!!!!!!
if(type == itm_coffee_raw)
{
int pleaseStop = 0;
if(pleaseStop == 0) //BREAKPOINT IS ON THIS LINE
bool dontstoptillyougetenough = true;
}
if (itypes[type]->count_by_charges() && req > 0) //GAME BREAKS HERE
{
if (crafting_inv.has_charges(type, req))
{
has_comp = true;
break;
}
}
else if (crafting_inv.has_amount(type, abs(req)))
{
has_comp = true;
break;
}
}
The code inside the if body doesn't really do anything, so the compiler could see it as "dead code" and remove it from the executable in an optimization pass. This means that the code in question doesn't actually exist in the final executable, and so you can't put a breakpoint there.
Turn off optimizations (always good when debugging in general) and it should work.
Related
Is break the most efficient way to exit a loop? In the code snippet below, would line A or line B be the more efficient way to exit the loop? Any links to material on how the break instruction works under the hood would be appreciated.
for (int i = 0; i < 10; i++) {
cout << i << endl;
if (i == 3) {
break; // A
i = 15; // B
}
}
I assume the difference is trivial in most situations, and that A is faster because B requires an assignment, an increment, and then a comparison, but I don't actually know how break works and it's better to know than assume. Thanks!
Let's compile the following code and look at the assembly:
#include <stdio.h>
int loop_with_break() {
for (int i = 0; i < 10; i ++) {
puts("Hello, world!");
if (i == 3) {
break;
}
}
}
int loop_with_assignment() {
for (int i = 0; i < 10; i ++) {
puts("Hello, world!");
if (i == 3) {
i = 10;
}
}
}
int main() {
loop_with_break();
loop_with_assignment();
}
As you can see, when you use break, if i == 3, it'll jump straight out of the loop to the end of the function, whereas if you use i = 10, it'll set i to 10, increment it by 1, then do the comparison, which is slower. However, this was compiled with no optimizations. If you use optimizations, they both end up becoming the same thing. However, since break is more readable and these optimizations are not guaranteed, you should use it for breaking out of loops.
The keyword break will just quit the loop without any comparison made in the loop condition. If you use i = 15 syntax, the loop will iterate next time to verify whether the variable i is greater than 10, if so, then quit.
In short words, break will break the loop without thinking anything, whereas i = 15 will lead one more iteration to look if the condition satisfies it.
You're right! Actually break keyword is very faster for breaking loop!
In your example, if you use line A, then as soon as control reaches this statement, it will immediately break the loop.
On the other hand, if you use line B, then first the assignment will be performed and again the control will go to the condition checking and when the condition will get false then it will exit from the loop!
if you choose while loop you can prefer to make condition false in the while loop. But in this case using break make sense.
I'm currently struggling to debug the following code part. I'm using VS2015 community edition on windows 10.
[(BR)] is a breakpoint
The following is a (slimmed down) version of my code. I basically have nested for loops that extract all points (X&Y coordinates) from all gameObjects.
As you can see I set two breakpoints.
I hit the debug button and it stops at the first breakpoint - success. Important local variable counterVertices is zero. Great as well.
Then I hit continue. It goes TO THE SAME BREAKPOINT THREE TIMES.
Then I get to the second breakpoint. counterVertices shows zero. Why?
int counterVertices = 0;
int counterIndices = 0;
int beginningOfPolygon = 0;
//GetData
for (auto& it : this->gameObjects) { //Iterate over all gameObjects
beginningOfPolygon = counterIndices;
for (int i = 0; i < it->getOutline().getNumber(); i++) { //Iterate over all points of the gameObject
[(BR)]this->vertices[counterVertices] = it->getRenderPoint(i).x;
counterVertices++;
this->vertices[counterVertices] = it->getRenderPoint(i).y;
counterVertices++;
[(BR)]if (this->vertices[counterVertices-2] == this->vertices[counterVertices-1] && this->vertices[counterVertices-1] == 0.0f) {
cout << "A point on 0/0." << endl;
}
this->vertices[counterVertices] = 0.0f;
counterVertices++;
//Add Line to draw
this->indices[counterIndices * 2] = counterIndices;
this->indices[(counterIndices * 2) + 1] = counterIndices + 1;
counterIndices++;
}
this->indices[(counterIndices * 2) - 1] = beginningOfPolygon;
}
I'm completely lost as this isn't even the problem I wanted to solve in the first place but rather got stuck on trying to figure on my original issue.
Thanks already for your time
PS: I have screenshots of the whole thing and the process is recreatable. I can clean and rebuild the solution, restart and do a backflip. Debugging behaviour doesn't change.
PPS: The program behaves/works in a way that suggest that counterVertices is increased correctly but the debugger information contradicts that.
Make sure you have optimizations turned off. Optimizations can really make it hard to debug, as values will be held in registers and not stored until it needs to. And code flow can be very unintuitive.
I'm getting a C4702: unreachable code warning in a for loop; the strange thing is that - by breaking apart the components inside the parens - the warning points to the increment part. Here's a sample program that demonstrates this error:
int main()
{
int foo = 3;
for (int i = 0;
i < 999;
i++) // warning on this line
{
if (foo == 4);
{
break;
}
}
return 0;
}
I can't figure out what's wrong with this line, because the for loop looks very straight-forward.
You have a stray semicolon in your if-statement:
if (foo == 4);
Recall that for loops have the following structure:
for (initialisation; condition; increment/decrement)
statement
Execution will proceed in the following order:
initialisation
condition; if false then end
statement
increment/decrement
Go to step 2
If the compiler is warning about the increment/decrement being unreachable, it means that something before it is causing execution to always skip it - in this case, the stray semicolon causes the break to always execute, jumping out of the loop prematurely.
for (int i = 0;
i < 999;
i++) // warning on this line
{
if (foo == 4);
{
break;
}
}
This is same as
for (int i = 0;
i < 999;
)
{
if (foo == 4);
{
break;
}
i++; /* Note the increment here */
}
So anyways you are going to break because of the if(foo == 4); so i++ is not reachable
The problem (i.e. the unintended ;) is already described in two answers.
I just like to add that you should take a look at your compiler options setting. Many compilers can detect such "strange looking" code and give you a warning. For instance:
Warning: "empty body in an 'if' statement"
Further the compiler can be configured to treat all warnings as errors.
In other words - the compiler options can often help you finding "unintended code" so that you avoid wasting time.
BTW - the eclipse editor can even give a "suspicious semicolon" warning as soon as you type such an if-statement.
I was playing with the variable changes breakpoint modifier in Visual Studio 2012. From my understanding, the variable change modifier causes the debugger to break if the specified variable value changes from a previous location execution. I think that this would be useful in narrowing down memory overwrites. My very simple C++ code is this:
int main ()
{
printf("This program converts upper case chars to lower and vice versa\n");
char str[20]="lowercase";;
int i;
for (i=0; i < strlen(str); i++)
{
if (str[i]>=97 && str[i]<=122)
{
str[i]-=32;
}
else
{
str[i]+=32;
}
}
str[1] = 'o';
printf("%s\n",str);
system("PAUSE");
}
Now I set conditional breakpoint on two lines
str[i]=str[i]-32
printf("%s\n", str)
to hit when array str changes. To do this I set a location breakpoint, then select "condition" on right clicking and in the condition textbox I put str,20. Finally I select the "has changed" radio button.
Now what I'm seeing is this:
The breakpoint is hit everytime on the line str[i]-=32, but never on the line printf("%s\n", str) and I'm curious as to why. Obviously the array has changed because of the line preceding the printf statement, so why isn't the breakpoint hit?
What am I missing here?
You are only breaking when that memory is written, not read. The function printf only reads that memory.
#include <iostream>
#include <vector>
using namespace std;
int in;
bool isPrime(int n) {
for (int i = 3; i <= n; i ++) {
if (n%i != 0) {
return false;
}
}
return true;
}
vector<int>* generateVector(int n) {
vector<int> v;
for (int i = 2; i < 20; i ++) {
if (i == n) {
continue;
}
if (isPrime(i+n)) {
v.push_back(i);
}
}
}
int main()
{
while(1) {
cin >> in;
vector<int>* nVectors[21];
for (int i = 1; i <= 20; i ++) {
nVectors[i] = generateVector(i);
} <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
}
}
This some c++ code. And i would like to make a break point just after the for loop(the arrow show the position).
I have found one way to solve it through adding a statement after it then make break point in this statement. But adding a statement without a meaning make not feeling good. So is there a better solution?
I am using GDB for debugging.
PS: I have already known how to set breakpoint in gdb. My intent is to break after the for loop ends, and display what in nVectors. Thanks.
Sorry for all. It's not the issue about the gdb or debugging skill, but there is a bug in my code. So when i print nVectors, nothing was printed. After fixing it, every method you provides works fine. Thanks.
You can use a assembly break point, just need to understand the assembly code of for loop.
gdb <your_bin>
layout split
break *0x80488ad #assmebly code will look like
#0x80488ad jmp 0x8048874 <main+18>
gdb has a command to add break points
there are a couple of ways, but I think the one that might help you is :
(gdb) break filename:linenumber
so for example I want to break at line 10 in main.c
break main.c:10
you might want try a tutorial http://www.yolinux.com/TUTORIALS/GDB-Commands.html
Nope there has to be some statement for the debugger to be able to set breakpoint.
I don't think there is a way to directly do what you want but you can still do it. Set a breakpoint on the last statement of the loop. When the debugger breaks switch the disassembly view and scroll down until you find where you want to place the real breakpoint. This will effective set a breakpoint at a specific address rather than on a line number in a source file.
You can specify the source file and line of the end of the loop, like so, on the gdb command line:
b file.c:123
If you want to go right after the for loop, you'll want to actually set the break for the line of the closing bracket of the while() loop, I believe. But you can try both and see what gives the desired result.
Try to use until command. It is useful to avoid single stepping through a loop. Also from gdb manual:
until always stops your program if it attempts to exit the current
stack frame.
If it was me, I'd set an assembly breakpoint, like the others said. But if you don't want to get into that, there's a simpler way: Since you know the loop count (20), and it is not very big, you can set a breakpoint on the last statement inside the loop (in your case, the only statement inside the loop), with the condition
if (i == 19)
Alternatively, you can set an ignore count:
ignore bnum 19
where bnum is the breakpoint number. This is probably faster, but in your case the difference will be negligible.
See Breakpoints, watchpoints, and catchpoints in the gdb documentation for more information.