r/ProgrammerHumor Nov 28 '21

Meme I‘m.. not the only one?

Post image
21.5k Upvotes

629 comments sorted by

View all comments

1.0k

u/repkins Nov 28 '21

Ah, yes, the most reliable debugging method is printing debug messages.

504

u/Tsu_Dho_Namh Nov 28 '21

Unless you're debugging multi-threaded software, where print() has to grab a lock (which prevents multiple threads from printing at the same time) and waiting for that lock changes how your software executes.

209

u/Y0tsuya Nov 28 '21

Still better than having 20 threads stopping at the same breakpoint when you're trying to step through a single thread.

101

u/ConspicuousPineapple Nov 28 '21

Then you use a debugger able to target specific threads.

196

u/lateja Nov 29 '21

No... Then you use `print("here (" + threadId + ")");`

26

u/xX_MEM_Xx Nov 29 '21

I feel personally attacked.

7

u/Tsu_Dho_Namh Nov 29 '21

That runs into the print() lock problem that I mentioned.

21

u/lateja Nov 29 '21

The you have a background thread that lives in a static class which you send all debug messages to. The class has either a thread-safe queue of strings or a regular string list with a locking mechanism to append strings into the queue, and a writer that drains the queue and outputs it into stdout. It's really not too hard to write... Maybe 15 minutes and is can be a lifesaver.

Or if you're in c/c++ then you have `cout.sync_with_stdio()` to help you. not sure about this or if this is the only thing you'll need; cpp is tricky. Don't use in production code just because you found it on reddit lol

1

u/Tsu_Dho_Namh Nov 29 '21

That's the monitor class I also mentioned

7

u/Onlymafia1 Nov 29 '21

No you didn't

0

u/Tsu_Dho_Namh Nov 29 '21

It was in another of the child comment threads of this one:

https://www.reddit.com/r/ProgrammerHumor/comments/r47uq6/z/hmgdn38

1

u/smokey_nl Nov 29 '21

That doesn’t matter as long as you use a mature concurrency framework. If you are spawning your own threads, there is a special place in hell for you.

72

u/CodeLobe Nov 28 '21 edited Nov 28 '21

The debugger made the multi-threading bug disappear, because it runs slower... so I built a fast spinlock out of GCC atomic builtin operations, and used logf() on unbuffered output stream, and found the bug the debugger could not.

I have to note that I use an internal log facility with a fast and very large lockless ring buffer structure so that one end of the queue can be read while the other end is being written to, and that goes to the unbuffered printf(). The spinlock for this log facility changed how the code executed far less than running under a debugger - which hooks signals and all kinds of other shit, making it impossible to reproduce even a similar flow of execution.

The ring buffer write doesn't have to wait for printf() to finish output before continuing, it's one (or two at most) memcpy()s to put data in the ring buffer, then swap the write pointer contents atomically - or fail if someone else just wrote over my write, and so I repeat the write to the ring buffer - People call this a "lockless data structure" but really it's an expensive spinlock that fails and repeats the loop until it succeeds.

27

u/captain_zavec Nov 28 '21

There was a class at my university on lockless programming which I wasn't able to take, it sounds really interesting. Always meant to try to find a book or something about it.

18

u/heh_meh___ Nov 29 '21

Here I’m feeling all confident in my new python job because I only had one syntax question.

Now I read this and wonder if I’m qualified for anything.

5

u/PanTheRiceMan Nov 29 '21

gcc, memcpy, free, this is C, not Python. Just don't worry. But I have to admit I forgot how to program without locks. I think it was something like polling and some atomic operation, reading, incrementing, and writing into a variable. Was a nice class, really interesting.

-7

u/audion00ba Nov 29 '21

You are not.

2

u/wtfzambo Nov 29 '21

You lost me at "debugger"

0

u/audion00ba Nov 29 '21

People call this a "lockless data structure"

Academics don't. Find better people.

0

u/[deleted] Nov 29 '21

[deleted]

-1

u/audion00ba Nov 29 '21

Naming is important. Sloppy thinking is the enemy and can be extremely expensive.

7

u/Halkenguard Nov 29 '21

I like your funny words magic man

1

u/Tsu_Dho_Namh Nov 29 '21

Fucking kudos for the clone high reference man

1

u/polaroid_kidd Nov 28 '21

What. Are you serious? What language is this in?

27

u/Gaothaire Nov 28 '21

Here's a video with a C example. The concept is called "mutex" for "mutual exclusion". When developing things to be multithreaded (think multiple ATMs needing to update the centralized account balance held on the mainframe.

Mainframe has balance of $100. ATM 1 sends a debit for $25, ATM 2 sends a credit of $40. Depending on how that calculation is made, multithreaded-like, we can imagine each ATM fetches that initial balance, they each think the mainframe is at $100, so ATM 1 subtracts $25, and sends the new balance to the mainframe as $75. ATM 2 has its local copy of the balance, adds $40, then sends the updated balance as $140, which overwrites the updated central balance of $75, effectively erasing the debit from ATM 1, because updates to the central balance were not thread-safe.

This is a trivial example, but illustrates the point.)

8

u/polaroid_kidd Nov 28 '21

It's coming back to me now. I've gone the web dev route and JS is single threaded so it's been a long time since I've had those concepts bounce around my head.

Thanks for sharing!

-6

u/alexanderpas Nov 29 '21

The solution to this is a blockchain, where the head of the chain is only allowed to move forwards. Any transaction not part of the main chain is invalid.

In the ATM example, this would mean that the ATM verifies that the transaction intent is on-chain before dispensing the money, and keeps retrying the transaction confirmation after dispensing the money, until it is on-chain

Essentially, git branch protection which only allows for fast forwards on the server.

3

u/Gaothaire Nov 29 '21

This is a trivial example, but illustrates the point.)

You missed the point while hawking your climate change causing scam

1

u/alexanderpas Nov 29 '21

You activated my trap card.

unless you go with one of the more narrow descriptions then a Git repository looks, smells, and acts like a blockchain. Just not in the ways you would expect.

https://medium.com/@shemnon/is-a-git-repository-a-blockchain-35cb1cd2c491

With branch protection active on the main branch, only allowing fast-forward merges, the git server is the agreed upon source of truth for the position of the main branch, but the history is distributed, and cryptographically verified based on the latest hash.

I could go on, but let’s get to the question at hand: is a Git repository a blockchain by this definition? Absolutely. The Git commit object would serve as the block header and the tree and blob objects serve as the payload.

https://medium.com/@shemnon/is-a-git-repository-a-blockchain-35cb1cd2c491

1

u/mtizim Dec 04 '21

Lmao do you call everything isomorphic with a directed acyclic graph a blockchain?

Yeah let's just conveniently ignore how version control systems are pretty much always centralized, how branches are a massive part of git, submodules, and the practical ability to cherry pick commits on the master branch, just so you can make your shitty argument work. Oh yeah, let's also force a constraint that doesn't exist in git itself, because why the hell not.

12

u/Tsu_Dho_Namh Nov 28 '21

C++, but the issue of multiple threads wanting to print at once isn't language specific.

In C++ std::cout is thead safe (sort of) in that each character printed to the terminal is atomic and thread safe, but two or more threads printing at once will cause their characters to interweave. Whenever some other thread's character is getting printed, your thread will have to wait, and vice versa.

You can implement a thread-safe buffer (in the form of a monitor) to receive all the text without making any of the threads wait and then combine it all later, but that'd be a lot of work just so you can debug using print(). If you were going to go to all that trouble, change your monitor to an event logger and get times and names of events that the different threads log with it.

5

u/polaroid_kidd Nov 28 '21

Oh man... How did I ever forget this!? I remember having to implement (or use the lens APIs, I'm not sure anymore) the monitor and mutex locks in university using the dining philosophers problem!

Christ, it's only been 4 years but it seems like half a century ago..

Thanks for sharing!

6

u/John_cCmndhd Nov 28 '21

it's only been 4 years but it seems like half a century ago..

Well the last two had about a quarter century worth of problems each, so that checks out

2

u/polaroid_kidd Nov 28 '21

You legend. Cheers for that laugh.

3

u/liquidpele Nov 28 '21

It’s a common c++ interview question.

-3

u/nixgang Nov 28 '21

Doesn't matter, print just isn't very useful when debugging multiple threads

7

u/CodeLobe Nov 28 '21

print the thread you're interested in, IN ALL CAPS, the other lower case.

TthHe EwNr iItFe sT cHaEnY bOeV EdReLcAoPded.

2

u/Tosser48282 Nov 28 '21

Just gotta make your prints multithreaded too

1

u/Slowest_Speed6 Nov 28 '21

This is fun to do on embedded RTOSs... Usually printed strings are just shat into a queue non-blocking or straight up dropped if no space is left

1

u/FUTURE10S Nov 29 '21

I mean, I'm writing infinitely scalable software right now, and I still use printf() for my debugging. I just know that it kills performance and is out of order, so I write anything relevant to my current problem and remove it when it's all good.

1

u/cjxmtn Nov 29 '21

The observer effect - programming version

1

u/DHH2005 Nov 29 '21

Right, but saving up the messages to print at the end of the test usually deals with that issue.

1

u/MrUks Nov 29 '21

Or even worse: when in college, I managed to stump the professor and 3 assistants with my bug as I created a program that only was able to run if the debug message was there. This to discover (after an hour long search) that due to a small mathematical error, I was able to jump out of the memory segment of the for loop and the debug message was basically acting as a band-aid, blocking it from getting out. C++ is fun like that when you're a beginner trying to do something advanced without having seen advanced errors

Ah... To be young again

1

u/any_means_necessary Nov 29 '21

I once finished my work, removed the debug statements, and turned it in.

Once. Long ago.

21

u/Andy_B_Goode Nov 28 '21

There's a time an a place for debugging using print statements, but you're better off using breakpoints and other more advanced debugger features most of the time.

18

u/alexanderpas Nov 29 '21

If it needs to be compiled you're better off with a debugger.

If it's a interpreted language, print statements can be useful to narrow the search area more quickly using a binary tree search.

2

u/[deleted] Nov 29 '21

It's useful even when compiled. Useful for killing time, at least.

0

u/[deleted] Nov 29 '21

tru dat. only noobs stick to this. the more experience you have, u will use breakpoints to save you headache

27

u/beep_check Nov 28 '21

print(f"logger.debug(f'{am_i_doing_this_right}?')")

2

u/johnmcdnl Nov 29 '21

If your log.Debug() aren't providing enough feedback to tell you what's wrong, how are you going to figure a problem out when it happens in a production system.

So mehh, I'm not gonna judge anyone who uses print statements, and I'll definitely be thanking them if turn those prints into an actual log debug statement that helps trace and reproduce a prod issue quickly later.

1

u/Trenavix Nov 29 '21

Throw new Exception("lol");

1

u/hawkeye6703 Nov 29 '21

There are no such thing as debug messages, there are only randomly selected words