|
It's all hard until you swim in those waters for a while. I've got two answers that I would probably consider. #1: debugging what ended up being a hardware problem. I was working on a device with a microcontroller and it had a sleep mode where the micro would program an RTC, shut itself off and the RTC would trigger the board's wakeup circuit when its alarm fired. I'd already told the board designer of two or three hardware bugs that somehow (surprise!) turned out to be my software bugs. So this time I was a little more cautious. There was a more senior software engineer working with me, and he told me to check the schematic. I looked at the processor manual and the board schematic, and followed the traces to make sure I was doing it right. And I just couldn't find out what was wrong. So the senior sw eng said, "well, ok, if you're sure, then just probe the RTC pin with a scope." Wow. A o-scope. WTF is this gloriousness? So I got to learn a bunch about how to go from the board schematic to the board layout, how to probe, what all the stuff on the scope was about. Sure enough, the RTC alarm went off on schedule but the trace showed some funny stuff that indicated that there was a design error in the board somewhere (I didn't understand the details, but IIRC a cut-and-jump of the prototype made the bug go away). Motto: It's never a hardware design bug. Until it is. #2: This bug I learned a good amount from. I would see frequent misbehavior in my code where it looked like multiple subsequent sessions were being corrupted somehow, perhaps from a previous session. I was certain that I was releasing resources from the previous session and destroying all of it. I watched my code hit my `boost::shared_ptr<foo_t>::reset()` and so clearly it was now gone. Right? Well, shared_ptr<> not all it's cracked up to be. So I went back to read about conventional advice about shared_ptr<> and people would frequently suggest boost::weak_ptr<> where appropriate. I mistakenly thought about these as a dichotomy for some reason. But that was no good because I couldn't share my weak_ptr<> so it's not really useful. Except -- wait -- the vast majority of the time I'm propagating my shared_ptr to places where they don't need to share it beyond themselves. So my design would actually be better if I shared the shared_ptr as a weak_ptr anywhere other than Right Here. In doing this redesign, I realized that the weak_ptr promotes itself temporarily by effectively asking "hey is this still allocated somewhere?" Turns out that other thread using this resource would occasionally take slightly longer and wouldn't decrement its shared_ptr until after the new session had started, which would mean that the old resource was never destroyed. After the redesign in this case where the background thread loses the race it would just fail the weak_ptr<> promotion and harmlessly skip its activity. Motto: shared_ptr<> and weak_ptr<> help preserve an ownership metaphor. Which code Owns this memory/resource and which code is just "borrowing" it? |