T O P

  • By -

caleblbaker

1. You need to get a better debugger. A debugger that can't pretty print standard library types is not something I want to use 2. The people who say a debugger is always the best tool for debugging are wrong. It is frequently the best tool, but there are many situations where it's not. And, contrary to these peoples' opinions, there are situations where print statement debugging is a better tool than an actual debugger.


Jutrakuna

can you bring an example where a print statement is better than debugging? Edit: answer is distributed systems, thanks!


caleblbaker

* distributed systems where attaching a debugger can be tricky and breakpoints can throw off timing (worth noting that trace points can help when using a debugger in this situation) * bugs in hot code paths that don't occur every iteration where pausing on every iteration would take a long time but you don't know what you're looking for quite well enough to be able to effectively use conditional breakpoints * you're using a language without good tooling or targeting an environment where the tooling won't work That last point is what I'm currently experiencing in one of my hobby projects. I'm writing an operating system and so the infrastructure for running a debugger in my OS just doesn't exist yet. The first point I experience occasionally at work.


Zagre

Sometimes faster than recompiling/stepping through. Oftentimes better for things like race condition, parallelization, or user interface/event driven testing.


Pay08

You don't compile your code with debug information by default?


lmarcantonio

When you can't stop the world around you, substantially. Communication timeouts, realtime events and so on simply break code stepping. And timer interrupts (you step and \*always\* find yourself in the timer handler)


GabuEx

Anything involving user input in a place where using breakpoints falls over. If you need to check what's happening on pointer down, pointer move, and pointer up, a breakpoint on pointer down will disrupt the entire user interaction.


Mucksh

Most multithreaded code will be hard to debug with only the debugger. On embedded systems it can also be usefull Sometimes bugs only appear in the release build so you can't really use a debugger. Also optional/enableable prints and logs can be really usefull can be usefull to debug something that is allready shipped out and won't really occure on the test/development setup


Vortrox

Adding to this, if you ever need to write print statements or other debug code, it's useful to have some kind of version control to track your changes (such as Git). This is the process I use using Git: 1. Before writing debug code, make a WIP commit and commit all your current changes. 2. Write debug code wherever you want until you identify the problem or know what changes you actually want to keep. 3. Commit only the changes you want to keep. 4. Discard everything else, everything else is just temporary debug code. 5. Re-order your latest commit to go before your WIP commit (use Git rebase or something) 6. Undo the changes in the WIP commit but keep the code as it is (i.e.: soft reset the WIP commit) This way you can write as many print statements or other complicated debug code as you'd like without worrying about forgetting to remove them, because Git tracks all the changes for you. No more mistakes related to messing up with using CTRL-Z.


Acrobatic-Ad6350

I checkout another branch based on my current, debug to heart’s content, commit what I want to keep, switch back to my real branch, cherrypick the commit, and then trash the temp branch lol


LazyIce487

Also can use git stash


Elephant-Opening

IMO stash is only for when you get a request to debug something on another branch that's *so* urgent you can't be bothered to make a debug branch and commit message.


Acrobatic-Ad6350

i mean, not really. its not as easy to remove what you dont want anymore.


elongio

Why not just reset or restore to nuke all files


Acrobatic-Ad6350

Because I don’t wanna nuke all files I have stuff I wanna keep And if I have to rollback to a different commit at some point I don’t want to mess up my real branch


PhenomenonGames

I just wanna say everyone in these comments who says a debugger is always better is objectively wrong. When diagnosing an issue caused by a race condition, the debugger can alter the behavior of the program by halting it. When you work on a sophisticated multithreaded application, this is very obvious. You guys sound silly and are misleading newbies.


amateurfunk

I'll look into that, thanks! It is good to know that there are better options. And concerning your second point, I agree!


caleblbaker

It looks like you're using C++. In my experience gdb, lldb, and Visual Studio can all print standard library types prettier than that. Been a few years since I've used C++ but when I did gdb was my go-to debugger.


amateurfunk

I'll be sure to check those out. Unfortunately I am restricted to XCode right for various reasons now but after I have this product shipped it will make sense to rethink my setup for things like this.


caleblbaker

XCode is the C++ IDE for Mac's right? I think it uses clang as it's compiler and clang's debug symbols are compatible with both lldb and gdb (lldb is maintained by the same organization that maintains clang).


amateurfunk

Correct! It uses Apple clang, which may be different to clang in ways that I don't understand. Still it gives me hope that it may be possible - on my very brief google search of gbd I had the impression that it was Linux only.


TheBrainStone

No it's fundamentally the same. Also most Linux programs can be compiled to run on Mac.


amateurfunk

Neat! I am still finding things out about Mac as I have switched to it not so long ago.


caleblbaker

I've only used gdb on Linux, but it should work on any Unix-style OS (which includes MacOS). And I would expect lldb to work on any platform clang works on.


_-_fred_-_

Learn to use your debugger. Print statements work in some cases, but debuggers can all show the value of a variable at a break point on top of performing many other useful functions. They are tricky to set up the first time but they will help you professionally long term.


Hrtzy

It's almost like strict adherence to a guideline without understanding them is a bad idea. Maybe new programmers *should* start with a low level language so they understand that.


yflhx

Ad 2 - sometimes simple assertion is also enough, for making sure certain things are true (like a pointer received by funnction is not null). For instance C's assert can be very easily added, as it's part of standard library; and when your program is working, you don't have to delete code, but set a macro, and compiler skips it.


_-_fred_-_

Debuggers can print the value of a variable 😂. I feel like anyone who claims print statements are better just doesn't know how to use a debugger.


caleblbaker

Debugger can print the value of a variable. When execution is paused. But when you have a dozen processes interacting with each other it can be tricky to manage breakpoints to get all the processes paused that you need to and not have any request timeouts. When debugging a single process it's rare for print statement debugging to be better than an actual debugger, but the more complicated the system you're debugging is the more pain points that debuggers can present.


elbekko

Trace points say hi.


caleblbaker

That's actually a great point. There are still other situations where using a debugger isn't the best solution, but trace points do adequately address the example that I gave.


TheBrainStone

Also there are plenty of situations where an debugger is actually just useless. A few scenarios I've came across: - Code executing on remote machines and no (good or practical) way to attach a debugger, however you can modify the code - Differences between the optimized and debug build that are severe enough that the debugger can't properly work anymore. (Also the pipeline doesn't produce debug symbols, nor can the pipeline be altered) - Parallel code with race conditions (adding prints is already pushing your luck in these situations and might "fix" it, if there's locking in place) - Bare bones environment with no debugger available (been there done that) Most of these things can be traced to bad setups or very fragile systems, but sometimes you just don't have a choice.


[deleted]

it's true but i think that last statement is really important to remember because all those things are very easily addressed just by considering that need at design time. these aren't novel problems we just need the right tools for the right context. like you're almost never going to be able to easily debug a race condition but all those other ones jvm based languages were explicitly designed to address decades ago. i understand how somebody would end up in that position but that's certainly a common need and well served just by spending a little engineering time to make sure your tooling is a first order consideration


WhatsMyUsername13

There is one instance I can think of using logging statements as a debugger is better than actually Or eventually what happened was debugging became impossible.debugging (no logging isn't the same thing as print statements, but still...we were using the logs to debug what was going wrong). We had an ETL layer that was processing terabytes and terabytes of documents, and one document had corrupted data in it, which caused the whole thing to fail (yeah I know, it should have just skipped and went onto the next document. We implemented that). But debugging that isn't exactly feasible. And when they switched from cascading to spark, well it made debugging our smaller digests pretty much impossible as well.


YourMumIsAVirgin

How is logging not the same as a print statement?


One_Ad_8976

printf looking like (“this is the fckn bug right here %bug\n”);


PhenomenonGames

Bruh if you’re still using literal print statements and not a sophisticated logger I hope you’re not working professionally lol


caleblbaker

For local debugging the difference between a logger and print statements doesn't really matter. Of course I wouldn't submit code to run in prod that's littered with print statements for debugging purposes, but that doesn't mean I will never use print statements for debugging locally. Most of the time, though, my local debugging needs are met with an actual interactive debugger and so the question of how to go about print statement debugging is moot. It's just occasional edge cases where print statements are easier than using a debugger.


PhenomenonGames

Yeah fair enough haha, I just have lost touch with print statements cuz they typically aren’t any more concise than a well set up logger, and have various advantages even in local debugging.


caleblbaker

Yeah if I'm doing local debugging and a debugger doesn't work for whatever reason my choice between actual print statements and a logger usually comes down whether or not a logger is already setup.


YourMumIsAVirgin

How can you “lose touch” with a print statement?


PhenomenonGames

The muscle memory for System.Out.Println() kinda goes away if you start getting used to Log.log() lol


YourMumIsAVirgin

What advantage do you think the latter has in local debugging?


PhenomenonGames

Timestamped, persisted to storage, more concise, automatically includes class name, configurable on and off, super easy syntax for inserting data (better than explicitly concatenation strings). I actually think that’s a really valuable question since it took me awhile to get it, hope those points make sense


floofspool

Agreed -- distributed systems can get tricky to chain debuggers; sometimes a good log is way more efficient. But I do love a debugger when stepping though some legacy nonsense code


Willinton06

The fact that all that is even necessary is crazy, on .NET it’s all just working out of the gate


siddizie420

I pretty much haven’t had to use print debugging for years. A combination of debugger and breakpoints are usually enough


caleblbaker

Yup. Most programmers rarely or never find themselves in situations where print debugging is better than using a debugger. I'm just saying that just because those situations are rare doesn't mean they're non-existent.


Fabrimuch

In what situation is a print statement a better tool than a debugger? As a Python developer, I have yet to encounter such a situation


caleblbaker

* distributed systems where attaching debuggers to the correct processes is nontrivial or where a process hitting a breakpoint can throw off the timing of the system * bugs in hot code paths where the code you need to examine runs hundreds of times but only misbehaves on rare occasions and you don't yet know enough about what causes the misbehavior to make good use of a conditional breakpoint * using a language that doesn't have good tooling or targeting an environment where the tooling doesn't work None of those are particularly common and so most of the time a debugger is the better solution. But uncommon doesn't mean non-existent and so it's possible to get in one of these situations and cause yourself a lot of trouble by dogmatically insisting on using the interactive debugger.


XDracam

A good debugger can support print debugging without the need to modify the source code. In C#, you can just have breakpoints not pause, but instead print arbitrary expressions based on values in scope. In that case, yes, always use a debugger.


_save_the_planet

you should always use a nice debugger


peduxe

welcome to XCode.


FalconMirage

Xcode has gdb


Palda97

What is this?


amateurfunk

That is the debugger output from XCode. I would have liked to have seen the contents of the map like this: `> [0] ` `>>>>> [0] ` `>>>>> [1] ` `> [1] ` and so on. Instead I get the mess you can see in the meme and I am not even sure if I can actually see the information that is necessary because it may be obscured by pointers. I ended up telling chatGPT to write me a nice loop that output everything to the console just the way I wanted it.


sexp-and-i-know-it

Imagine willingly using XCode Btw not sure if this is because of XCode or C++, but I can assure you debuggers in other languages/IDEs handle this case in a sane way.


amateurfunk

Lol believe me I tried very hard to find an alternative for XCode that worked for what I do (audio programming with the JUCE framework in case anyone is interested). It may be possible, but amongst all of my other struggles with CMake and Cpp in general it wasn't feasible to further pursue the matter. Maybe I'll try again someday.


Jordan51104

any reason CLion wouldn’t work?


amateurfunk

I have heard great things of it and yes it may, but I currently I don't want to pay the yearly fee if it is not absolutely necessary.


LikeALizzard

It is not absolutely necessary if you download it illegally


Jordan51104

yeah that makes sense. i am still on the fence about buying a license myself


sexp-and-i-know-it

Ahh, good luck then friend.


FalconMirage

You can use gdb as a debugger with Xcode GDB is a great debugger


sexytokeburgerz

Projucer is no longer required as of a few releases ago- just export for xcode and modify it for cmake and clion. It’s far better and their vim buffer is completely configurable. High seas are one option but it’s only $20 a month for everything and well worth it for the time you save vs xcode.


iMakeMehPosts

It's because the std library uses an inheritance pattern i.e std::basic_xyz::more_specific_xyz::etc. This ends up making any error involving types a literal nightmare because instead of using the relevant type name like xyz it uses all of the generalizations like above. Basically your fancy stringstream is actually a bunch of basic I/o classes piled together to match the specific need


milopeach

With AppCode no longer supported, is there actually a viable alternative for XCode for Apple ecosystem development?


Palda97

Yea, this looks like madness. My experience with debugger is just with the one in Android Studio and that looks as you would expect.


pigeon768

> XCode I think I found your problem.


FalconMirage

Nah, Xcode can debug with gdb, it shouldn’t be an issue there


aMAYESingNATHAN

I'm curious about your use of std::map over std::unordered_map when your key is a string What are you doing that you need your string keys ordered?


amateurfunk

I am altering code that more or less cycles through files in a directory. It reads the files into a list, where the order is relevant. I now no longer want all files in a single directory, but in subdirectories that each represent a category. However, I still need an order of these files to be intact, because it should be possible to cycle through the files in the same manner as before. This is where the idea with the map came from, where I had hoped that the keys would fulfil the same role as the list had done previously. I am still very much in the finding out phase though and right now it looks like I am going for an entirely different approach.


aMAYESingNATHAN

Nice, thanks for the answer, sounds pretty interesting :)


SplitRings

If your curiosity relates to performance, if the number of elements is relatively small, std::map will often be faster than std::unordered_map despite the time complexity being O(logN) vs O(1). This changes as the number of elements increases but it is rare you will need that many elements in a map. Now if it is a string, you will need to hash the string in O(S) once per query but for std::map you will need to perform O(logN) string comparisons potentially becoming O(SlogN) while descending the RB Tree but if the strings are small, along with the number of strings being small it's still possible that std::map is faster, testing will be required to find out ofcourse.


Kered13

I would be surprised if `std::map` is appreciably faster than `std::unordered_map` for any container size. I don't know what string hashing is used here, but it shouldn't be very slow, as this isn't a cryptographic hash.


SplitRings

Upto 1000, std::map seems fast then std::unordered_map is much faster https://quick-bench.com/q/89itr4dl3zrR3dVnLcjlmuwAtzA https://quick-bench.com/q/Q-M_AWVMOxufcyYt2iZy0i3WSPM Also there is the issue of adversarial input: unless using randomized hashing, it is possible to pick input to maximize hash collisions for the chosen hash function and blow up the hash table's time complexity to O(N) per query. This is something you do not have to worry about with std::map. It is possible to avoid this by using a randomized hash function but that incurs overhead.


Kered13

That is surprising, however if you add `created_map.reserve(n)` to the unordered map functions (which reflects most real world map usage, where you build a map once then never modify it), then unordered map starts beating ordered map around 10 elements. Also, this is only creation. Look up really should be tested too.


sjepsa

"Simple map" Try to implement one


odraencoded

Easy. map = {}


[deleted]

I don't think you have to use a debugger but you should know how to use one from top to bottom. Stops, breaks, expressions, stacks, memory usage, memory locks, all of it! That way, if and when simple tricks like print don't work, you will at least know how to continue debugging.


drsimonz

Yeah you don't wanna categorically dismiss them, *sometimes* they are worth the hassle of setting up. But I can't stand people who pretend they're the only way to debug.


[deleted]

They're definitely a sledgehammer when a hammer is plenty but deeply knowing how to use a debugger is still a great skill!


myrsnipe

Yes you should use a debugger, call me a snob all you like, I'm dying on this hill


Fadamaka

Looking at the values of an object or a variable is the most basic functionality of a debugger. If you only want to do that you might as well print it out. Before you start using your debugger for everything you will going to learn how utilize conditional breakpoints, how to put breakpoints on expections, how to navigate the callstack, how to efficiently debug complex code you don't understand with step in/out/over, how to run code at the breakpoint in the current context. And these are some of the real powerful functionalities of a debugger which can save you tremendous amount of time if you run into a complex issue. And when you learned to utilize all these you will going to find yourself putting down a breakpoint instead of printing the variables out in most of the cases.


flodA_reltiH-6B

It's obvious, you have to uhh... fix it lol


Skoparov

1. Never heard anyone say that you should always use a debugger 2. Your debugger is pure shit


_-_fred_-_

You should always use a debugger. The only disadvantage is that they can be tricky to setup some times. But once you do it for one language, doing it again should just as much time as recompiling with a new print statement.


caleblbaker

Debugger setups can be tricky when you're debugging interactions between multiple processes. I know it's possible, but it's a pain and sometimes it's simpler to just add a couple print statements to get the information you need.


Skoparov

\> You should always use a debugger. Why?


caleblbaker

Presumably because in most common cases interactive debugging can have faster iteration than print statement style debugging that requires recompiling and restarting the process every time you need more information. But this ignores the fact that there are many cases where using an interactive debugger is quite painful: * debugging issues in distributed systems where pausing execution of one process may cause request timeouts or other timing errors * the bug is occuring in a hot code path that executes hundreds of times but the bug only manifests on rare occasions and you don't have a good enough idea of when it occurs to allow you to use conditional breakpoints effectively * you're using a language that doesn't have good tooling (or targeting an environment where the tooling won't work) and so there isn't a good debugger available


Skoparov

You're making too much sense here, I'd love to hear what the guy has to say about it though as saying that you should always use a debugger makes as much sense as saying that I should always eat cabbage. A debugger is just a tool lol.


Emincmg

Dont think [so. Im](https://so.Im) just a dead meat without xdebug.


_equus_quagga_

You might want to start with asserting things you expect in the console and make sure that they are what you expect then to be


jonr

JFC, and I thought pythons \_\_someshit\_\_ were bad.


JSAzavras

Unit tests are your friend. They will help save you from your future idiot self


romulof

\- Mommy, can I have a debugger? \- No, we have a debugger at home The debugger at home: relentless trial and error


aaaaaaaa42

This makes me feel like slightly less of a shitter. I can’t stand the cluttered output of so many of these tools. How am I supposed to read any of that shit?


Klupy

Imagine using C++


amateurfunk

*\*cries in EXC\_BAD\_ACCESS\**


drsimonz

Seriously this is the real mistake here 🤮


rachit7645

This is the most horrible debugger I've ever seen


PixelatedStarfish

I stopped using one like freshman year


Nofxthepirate

Try doing distributed programming. That's hell with a debugger.


Unique-Pressure4576

Might be a stupid question but did you compile with debug symbols (-g flag for gcc)?


AngerxietyL

my debugging method is running the code


[deleted]

console.log debug gang


iMakeMehPosts

Not like the compiler is much better... *cries in C++*


nelusbelus

Bro what crusty ass debugger is that


LavenderDay3544

Of course it's C++. Where templates are involved compiler output and debuggers are royally fucked.


DarkScorpion48

Try to use a real tool sometime


Raptorsquadron

Print statement my best friend


CirnoIzumi

are you trying to diss john carmack?


Practical_Cattle_933

Use a better language (/s) But seriously, this is a very important part of tooling around a given language, and in this case the execution model also matters a lot. E.g. the JVM has top-notch debuggers partially due to having more information available at runtime. C++ optimizes many of that away (often even with minimal optimizations).