Monday morning, 10:00AM. As per usual, today's protagonist, Merv, got some coffee and settled in for his usual Monday morning routine of checking Facebook and trying to drag his brain into some semblance of gear. As he waited, the least interesting conversation ever floated to his ears from the hallway:
"It's like, yak butter, I guess? I put it in my coffee, it's supposed to do wonders."
"No way, man, I can't do dairy."
"Yeah, but it's not dairy, it's yak."
"Like, yak meat?"
"No, like, butter from yak milk."
"Then I can't have it. I'm allergic to dairy."
Merv was so stunned by the inanity of the conversation that his groggy brain didn't clue in on the obvious sign. Of course, the non-dairy drinker would be Sergey. Normally, Merv would have avoided the man this early on a Monday. He had a way of coming up with the weirdest, most bizzare problems when he debugged code, and he always ran straight to Merv to untangle them.
"Merv!" Sergey appeared, leaned into his cube. "Just the guy I was looking for. Do you have a minute?"
Begrudgingly, Merv conceded that he did, in fact, have a minute. And so, a few moments later, he found himself standing behind Sergey's chair, trying to remember what exactly this product did while Sergey explained.
"See, this data here, watch carefully while I run it—there it is. See that? It changed. I don't know why or when, but something's overwriting the data I put there. So I figured it must be here, but look, there's no assignment in this method, or this one."
"Can't you just debug through it?" asked a sleepy Merv.
"That's the weird part: it doesn't do it if I build in debug mode."
Merv frowned. "Run that by me again?"
So Sergey did. Of course, it was silly to step through a release build. There were no debugging symbols, so it was hard to tell what was going on. Merv showed him how to enable debugging symbols in a release build, but the compiler's optimizations made it hard to step through something like this. The more they dug, the weirder the behavior seemed, and the saltier the language got around the monitor.
Could it be an optimization bug in the compiler? Maybe memory values weren't being set correctly in the release build? Was it a race condition where the debugger was changing the timing? Nothing seemed right. Finally, as Merv's brain shifted into high gear, he looked over the exact lines the change was being made in.
"Here, the copy is made. I can see the value. But as we step through the next few lines, it changes, without being touched."
The code was just a simple assignment using a basic equals sign. Feeling a headache coming on, Merv tapped the equals on screen. "What exactly does that copy assignment operator do, for this class?"
They went digging. What they found was beyond the pale: macro magic changed how the function worked depending on how it was compiled. In debug mode, it was a deep copy. In release mode, it was a shallow copy; the returned object was little more than a pointer to the old one. So in release mode, changing the original (off in another thread) also changed the copy, while in debug mode, they were separate objects with their own lifetimes.
"I need more coffee," Merv muttered.
"Me too, buddy," replied Sergey.
Neither of them budged.
"Who wrote this?" demanded Merv.
The commit logs revealed the name: Patrice, who had once committed a 3000 line monstrosity all in one commit that Merv had had to rewrite from scratch. That had taken him four mugs of coffee to get through. Faced with the prospect of digging through the whole codebase to every assignment and guess if they wanted a deep or shallow copy, Merv knew the right answer: he'd have to put in a catering order with the local coffeehouse. He'd break the machine before he was done.