4 ms·
I did this a long time ago with macros. It helped me to find a ton of leaks in a huge video codec codebase. I still don't understand the hate for the C preproc
by rqtwteye 2y ago
I did this a long time ago with macros. It helped me to find a ton of leaks in a huge video codec codebase.
I still don't understand the hate for the C preprocessor. It enables doing this like this without any overhead. Set a flag and you get constructor/destructor logging and whatever else you want. Don't set it and you get the regular behavior. Zero overhead.
- jonathrg 2y agoThe hate might have to do with it being such a primitive and blunt tool; doing anything moderately complex becomes extremely complicated and fragile.
- tialaramex 2y agoYeah, this very primitive tool easily creates the programming equivalent of the "iwizard problem". [You replace straight forwardly "mage" with "wizard" and oops, now your images are "iwizards" and your "magenta" is "wizardnta"]
- deleted 2y ago[deleted]
- immibis 2y agoBy contrast something like AspectJ for C++ (if such a thing existed) could express this requirement cleanly.
- akira2501 2y agoComplex arrangements _are_ fragile. There is no magic environment that can fix this for you. If you feel you've seen one, then you've focused on the parts of it that were important to you, while ignoring the parts of it everyone else actually needs.
- synergy20 2y agodo you have a write-up how you did it? I'm interested, thanks.
- naruhodo 2y agoI did a similar thing, in C++, 3 decades ago. I used a macro, FUNC(), that I would put at the start of functions. It took no arguments and declared a local instance, using the __FUNC__ preprocessor builtin to pass the function name to the Trace constructor: Trace trace##__LINE__(__FUNC__); The Trace instance would generate one log on construction and another on destruction. It also kept track of function call nesting (a counter) in a static member that would increment in the constructor and decrement in the destructor. It was inherently single-threaded, because I used a static member, but it could be adapted to multiple threads using thread local storage. I paired it with a LINE("Var x is " << x); macro for arbitrary ostreams-style logging. And building on that, EXPR(x) would do LINE(#x " = " << (x)). The output was along the lines of: ,- A::f() | ,- A::g() | | ,- B::B() | | `- B::~B() | | x = 12 | | About to do a thing... | | ,- A::doAThing() | | `- A::doAThing() | `- A::g() `- A::f() The macros could be disabled (defined to do nothing) by a preprocessor symbol.
- synergy20 2y agogcc's -finstrument-functions can also add the function call traces without changing the code I think