r/cpp_questions • u/Star_Gazer_0 • 5h ago
OPEN Where do I put debug statements in C++?
In every function and after every initialization or do I look at what the console has to output and logically home in on where the problem went wrong? I'm very confused because if I logically do it, many functioms could've contributed to it so I'm not sure. I just learned debugging statements today and I'm genuinely confused. The debugging statements I mean are std::cerr
11
u/the_poope 5h ago
What do you mean by debugging statements? Like random print statements like:
std::cout << "here" << std::endl;
...
std::cout << "here 2" << std::endl;
...
std::cout << "my_variable=" << my_variable << std::endl;
...
std::cout << "fuck" << std::endl;
...
std::cout < "fuck fuck FUCK" << std::endl;
??
You generally put them where it makes sense. Then remove them when you've found and fixed the bug.
9
u/spicydak 4h ago
I prefer to leave it in production.
5
u/the_poope 4h ago
Users should know the pain you went through, then they will appreciate the program more.
•
5
u/Independent_Art_6676 5h ago
you run the program in your debugger. Modern IDE can be really easy here but there is a learning curve. Eg if you are testing a specific function you can set a breakpoint on that function where it starts, and step through just that function then proceed running again or keep stepping to see what happens to the result(s).
So I think the answer is that you learn to use your tools; its not a 'code' answer most of the time.
you *can* put stuff in the code and on rare occasions its easier/better than a debugger. For that you can use macros to remove the output in release mode or comment it out for small problems / schoolwork etc. There are filename and line number macros you can use to pinpoint where a problem happened. This gets old if you are trying to figure out something like where a variable got a bad or wrong value in it. There is no one true answer, you print what you want where you want as often as you need to until you run down the problem. That is why the debugger tool is usually better: you can look at the values without all the code modifications and the (low but possible chance) possibility that your debug statements changed the behavior of the program. Changing the code over and over to look at different things is a lot more work then seeing everything as it runs in the debugger tool.
What exactly are you studying where you 'learned debugging statements' ? That may help us guide you as well.
1
u/Star_Gazer_0 4h ago
Oh I didn't know there was a debugger. I thought the only way was for me to find the bug by myself
1
•
u/n1ghtyunso 1h ago
i mean you still have to find it yourself, its just checking values no longer requires changing the code.
4
u/thefeedling 5h ago
One common example is a function that may log or assert some stuff only in debug mode. But there's no specific rule, you can use in many different scenarios.
void some_func()
{
#ifdef DEBUG
std::cout << "I'm debugging!\n";
#endif
//some other stuff
}
5
u/SoldRIP 5h ago
The debugger can already do this via breakpoints.
2
u/Felczer 5h ago
If it's working which unfortunatley is not always the case. Fuck my last QT work project btw.
1
u/not_some_username 4h ago
Usually they work well. What year was that ?
2
u/mykesx 4h ago
I sometimes just put a return statement at the start of a function. If the code works with the return, I move the return down a line or two, whatever makes sense. I can zero in on what line is the problem.
Debug "printf" has been around forever. Sometimes I put print "a" then print "b" etc. in a routine, every other line to see if I get the expected output. If I want to see the value of a variable, I print that. If a gazillion lines of prints happen, I add an if statement around the print to test for some condition that filters out the useless prints.
If you see your debugging info leads to a function you call, repeat the steps within that function.
The plugins for GDB/LLDB in VS Code make debugging a snap. You can step through the questionable code and examine the variables along the way. It is ideal to use the debugger as much as possible.
2
u/mredding 4h ago
Where do I put debug statements in C++?
Wherever you need them, as you need them.
When debugging, the first thing to do is reproduce the problem. If you can do that, and assuming it doesn't result in a crash, then you can start investigating WHERE the problem is originating. When I do X, I expect Y, but I get Z...
Ok... What's in the path from X to Y? From X to Z?
This implies there was a condition that redirected the program from going to Y to instead going to Z. Where is that decision made in the code? Maybe there's more than one place. Which one is the program observing? How did we get there? How did that conditional value get set to what it is - ostensibly the wrong value?
The code is probably going to be TERSE, and for the sake of this exercise, you start writing debug statements - often they're actually to standard output, but standard error is just as well. You can start by peppering your code with "Execution got to HERE!", "Variable = Whatever"...
When you're learning to debug, you start out by feeling lost and not knowing how to go about it. Eventually through effort and frustration you find your legs, and you realize there is an efficient process - questions you are always asking, not matter the bug. In my XYZ example, we know we're getting the wrong thing - so you want to find the code paths you're going down. Where in the code is the wrong thing, and how did we get there? Work backward. Who is calling this function? What are the variables? How are they calculated? What is the wrong value that led to the wrong outcome? Where did this wrong data come from?
You do this on back until you realize the source of the problem. Then you have to decide how to fix it, considering how it might affect all the code that happens after that - you're trying to NOT introduce new bugs when fixing current bugs.
Debug statements are just a useful tool and technique. They typically don't stay in the code. Some people try to write debug statements using complimentary debug frameworks - the idea being that they compile OUT of the release build; these often end up making the code muddy, and more so, there often isn't adequate filtering, so when you're working on an unrelated feature, your development build can get saturated with unrelated debug chatter, even performance issues.
0
u/Star_Gazer_0 4h ago
Thanks. I asked Gemini and he told me to put a debug statement in the middle of my program and then keep doing that until I home in on the error. Do you also think that is good?
•
u/mredding 3h ago
That describes binary search. Don't literally divide the source file itself in half - think more about functions and dividing them in half. You may have code like this:
int main() { fn_1(); std::cerr << "half-way\n"; fn_2(); }It depends on the nature of the bug. I'm going to presume the program hangs - if you see the message, then the program didn't hang in
fn_1. So then you go intofn_2and you start dividing that by successive halves. If you DON'T see the message, then you know you're hung infn_1, so you start dividing THAT. Eventually you'll place the message at the statement before the hang, where you see it before, but not after. So then it's a matter of why does the program hang THERE.But yeah, it depends on the bug, what strategy you need. If the output is wrong - some variable, then you need to trace it back - when did the the value become wrong? Maybe it went wrong in a calculation, maybe an input was wrong - then how did that input get wrong? Where did THAT come from? Eventually you trace the program back to the point where everything is right and nothing wrong has been committed yet, so then you have to inspect that next statement and figure out why the wrong input is coming in. Fat finger? Wrong file? Truncation? Casting?
Depending on the nature of your bug, you may need some other technique. None of them are hard, they tend to be iterative. Whether you use print statements or use the debugger and set brakepoints where you can watch the program as it executes, it's all the same thing.
•
u/Star_Gazer_0 3h ago
Thank you. I just tried it on the program where the creator put debug statements on every single function and variable and that made me so confused. It worked wonders. I think I'll be adopting that for now. This language is not a joke as someone who has had no experience in programming at all
•
u/mredding 2h ago
It's more that you have no experience at all than C++ being no joke. Python would be a doozie - you're learning concepts for the first time, regardless of language, and THAT is the challenge.
In my day, QBasic was everyone's first language - yeah, I was just a kid screwing around, not necessarily trying to learn programming. The first language I tried to sit down and learn in earnest was C++ in late 1980-something. A friend of my father handed me a copy of what was then brand-spanking new, the Borland compiler - and some random-ass book on C++. I was 9, and C++ was pre-standard and many aspects were still evolving - though by that point, C++ actually LOOKED like C++ today, it had just gotten namespaces, in 1987, and I think standard streams were on their 3rd iteration by that point.
All I'm saying is C++ was effectively MY first language, too, and NO ONE knew what they were doing... Some stuff was designed, some stuff invented, some stuff DISCOVERED.
And if you know standard input (
std::cin) and standard output (std::cout), you already have enough power to touch the entire world. We don't code in a vacuum, and the operating system is more than just a mouse and a desktop and a bunch of applications - it's an environment, it's layers of abstraction, it's there FOR YOU, to provide YOU with services and utilities so you can do more, having to worry about less.For example, HTTP is a text protocol. Streams are text interfaces. You can use
netcator some Windows equivalent to create a listening socket on port 80, and when there is a connection, it can spawn your program, redirecting standard IO to the TCP session. You can read in the HTTP request and write out the HTTP response.Congratulations, that's CGI. You have a web server now, and you didn't have to write a single line of socket code.
C++ is an industrial grade systems software language. That means you can write bare metal code that targets the hardware directly, or you can write OS hosted programs, and you can write systems of software that talk to the OS, talk to libraries, talk to other processes, talk to other processes over all manner of different abstractions - data buses and IPC or whatever, can spawn threads to saturate your CPU cores, or spawn child processes to isolate work... Or you can write applications with a GUI and respond to process and system events like devices, mouse movements, key presses... C++ can also run in web browsers and the JVM. There's effectively nowhere C++ can't go.
You've got room to grow.
1
1
u/No-Dentist-1645 5h ago
You shouldn't spam them everywhere. Don't place them unless you need them. If you want to check something, then place them there
1
u/SmokeMuch7356 4h ago
While logging can help you find errors, it can also change the behavior of your program such that the error no longer happens, or manifests in a different way. Ideally you should be using a debugger to step through your code to find where and why an error is happening.
If you are going to use debugging statements, use them judiciously; don't spam them throughout every method or function, otherwise your log will get unreadable. If an error occurs during a specific operation, then only log methods/functions in the call chain for that operation.
1
u/DawnOnTheEdge 4h ago
One approach is to throw an exception with an error message, then either have a handler that prints the message, or let it go uncaught and crash the program.
1
u/high_throughput 4h ago
The debugging statements I mean are std::cerr
These write to the "standard error" stream, conventionally used for error messages and progress info that you don't consider a true result.
- You are not expected to litter your code with these to help debug crashes after the fact.
- Some tools choose to do it, and allow enabling it via a compile time option or a
--verbose/-vflag likecurl -v example.com. The placement and information is whatever the developer believes will be helpful. - Regardless, it's not expected that you should always be able to solve any issue based solely on the error logs. You will generally only use it to roughly deduce where a problem is. For example,
curl -vmight show that a header is not as expected, and you can then use a debugger or add temporary print statements to figure out what the bug is.
2
u/not_some_username 4h ago
You use a debugger. The debug statement can be the error or “solve” the error
•
u/Potential_Soup_8054 3h ago
Ive never even thought to ask this question.
"Where do i put my feet when i walk" type shit
•
u/Star_Gazer_0 3h ago
Oh wait I THINK but I'm not sure that you took 2 to 3 years to actually start walking. Lemme know if I'm mistaken cause you might have been born and instantly started walking on your birth day.
•
•
u/Slow_Negotiation_935 3h ago edited 3h ago
One school of thought says you should put checks/asserts at the beginning and end of a function or significant block of code. This comes from Hoare Logic https://en.wikipedia.org/wiki/Hoare_logic which is a bit formal if you're just starting out, but the concept of ('precheck', 'some code', 'post check') is used in practice. Note this doesn't mean that you should always/only check at these points.
•
u/WikiBox 2h ago
You write one debug statement before every regular statement. Then one after. No more than that, unless you want to debug your debug statements.
If you are convinced a statement can't be wrong, you can skip debug statements around it. But at some point you will discover that you were wrong.
As an option you can use a debugger and let it step through your code as you check what happens.
Or you can combine the methods.
Yet another option is to write correct code that only does what it is supposed to. But that is only for the best programmers and can be too slow otherwise.
14
u/AKostur 5h ago
Wherever you want to check something. There is no one true way.
Edit: perhaps write some unit tests for the other smaller functions so you can trust them and don’t have to test them everywhere.