0

Sometimes, I want to figure out where an NullReferenceException (or the like) is thrown in my product's code without exposing any customer information. I have a tendency to do something like this (simplified example):

int flags = 0;
try{
    SomeOperation(foo.bar);
    flags |= 1 << 0;
    SomeOtherOperation(bar.foo);
    if (SomeCondition(baz.bar)){
        flags |= 1 << 1;
        stuff = bar.bar;
        flags |= 1 << 2;
    }
    while(SearchForStuff(bar.foo, foo.bar)){
        const int mask = (1 << 3) - 1;
        flags &= mask;
        flags |= 1 << 3;
        if (StuffExists(foo.bar.foo)){
            flags |= 1 << 4;
            DoThings(foo);
        }
    }
    flags |= 1 << 5;
    Baz result = bar.foo.DoBar(foo);
    flags |= 1 << 6;
    return result;
}
catch (NullPointerException e){
    SendCrashReport(e + " flags:" + flags);
}

My Question is is there a way to increment the bit shift at compile time such that one could add some logic and flag increments without having to modify the bit shifts for the following flag increments?

Edit: We are currently not including debugging symbols with the app, and I don't know if we ever will be.

Edit 2: I realized that |= might be better than += for the case of 1 << 32.

BrainStorm.exe
  • 1,565
  • 3
  • 23
  • 40
  • 2
    It would expose no customer information at all to divulge the exception's source location (assuming you've included symbols). If the concern is that the location might be in third-party code and you must exclude that somehow, new up a `StackTrace` and filter until you get to the first frame in your own code. (This does not require symbols.) Even if *all that* doesn't work, maintaining your own "program counters" is surely simpler than all this bit shifting trickiness. – Jeroen Mostert Feb 26 '18 at 16:11
  • If you do want to do complicated, non-optional transformations like this at compile time, your best bet is actually changing the compiler: extend Roslyn to maintain this counter for you on every line, or add some funky keyword/call to change it that translates to IL. But I still think this is massive overkill compared to just writing something that records the IL offset in your code; where this would not be enough, your method would not suffice either, since you're probably much more interested in the values of locals/parameters to reproduce the condition. – Jeroen Mostert Feb 26 '18 at 16:23
  • So you are suggesting I use something like `location = CurrentLocation()` with CurrentLocation defined here: https://stackoverflow.com/a/44976518/1366594? – BrainStorm.exe Feb 26 '18 at 16:30
  • I didn't. Although that's certainly also an option -- but one with a ton of overhead if you do this for every line, *just* to capture exception location info. If you're just doing this for certain "critical spots" it might be acceptable, but if you want to trace exceptions back to their source no matter where they occur, use the stack trace/IL offset. That's what it's there for, and it has no overhead. Translating the IL offset back to source is simple with symbols you have on your end, and perhaps a dash of [clrmd](https://github.com/microsoft/clrmd). – Jeroen Mostert Feb 26 '18 at 16:37
  • Looks like you want a C-style preprocessor macro. See this [answer](https://stackoverflow.com/a/25374427/500276) on using the MSVC preprocessor with *.cs files. – Mark Benningfield Feb 26 '18 at 16:37

0 Answers0