void catchCrash(int signum) { reportTrouble(); // - signal(signum, SIG_DFL); // exit(3); // } int main() { signal(SIGSEGV, catchCrash); //-- ... --// }
void reportTrouble() { void *callstack[128]; int frames = backtrace(callstack, 128); char **strs=backtrace_symbols(callstack, frames); // crash_report.txt // - , , etc FILE *f = fopen("crash_report.txt", "w"); if (f) { for(int i = 0; i < frames; ++i) { fprintf(f, "%s\n", strs[i]); } fclose(f); } free(strs); system("curl -A \"MyAppCrashReporter\" --form report_file=@\"crash_report.txt\" http://reports.myserver.com"); }
reinterpret_cast
all of us! So, to make the backtrack more interesting, we create the functions goCrash()
and crash(void *)
. int crash(void *obj) { Crasher *crasher = reinterpret_cast<Crasher *>(obj); crasher->doSomething(); return -1; } void goCrash() { const char *str = "Hello, crash!"; const char *str2 = "Hello again, crash!"; char str3[200]; sprintf(str3, "%s\t\t%s\n", str, str2); long long add = rand() % 20000 + 1500234000l; // fire in my leg! crash(reinterpret_cast<void *>(str3 - add)); }
Crasher
some previously unknown address. Very curious! Let's declare the class: #define P_DOUBLE_COUNT 10000 class Crasher { public: // c-tor Crasher() { myPrivateString = new char[100]; sprintf(myPrivateString, "%s\n", "that\'s my private string!"); myPrivateInteger = 100; for (int i = 0; i < P_DOUBLE_COUNT; ++i) myPrivateDoubles[i] = i / 100.0; } // func void doSomething() { // here we can (?) crash fprintf(stderr, "%s\n", "That\'sa function!"); doSomethingPrivate(); } private: void doSomethingPrivate() { // crash? oh, no... fprintf(stderr, "%s myPrivateInteger == %d\n", "That\'sa private function!", myPrivateInteger); fprintf(stderr, "myPrivateDoubles[1] == %f\n", myPrivateDoubles[1]); fprintf(stderr, "myPrivateString == %p\n", myPrivateString); // still alive? crash! crash! crash! ((Crasher*)NULL)->doSomething(); } private: char *myPrivateString; int myPrivateInteger; double myPrivateDoubles[P_DOUBLE_COUNT]; };
doSomethingPrivate()
function, we all call the function at the null pointer. So, just in case. Suddenly, after calling doSomething()
for an undefined address, will the program still survive?curl
cursed that the server was not found. Well, this is nonsense, you can temporarily replace his call with cat crash_report.txt
order to see our crash report right away. So what else do we see?"That's a function!"
derived from the doSomething()
method! Interesting, isn't it? The pointer points to the sky, and the methods work? Well, not exactly.doSomethingPrivate()
, and the backtrack tells us eloquently about it: 0 segfault 0x000000010d0a98c8 _Z13reportTroublev + 40 1 segfault 0x000000010d0a99d0 _Z10catchCrashi + 16 2 libsystem_c.dylib 0x00007fff99b5dcfa _sigtramp + 26 3 ??? 0x00007fff00000000 0x0 + 140733193388032 4 segfault 0x000000010d0a9c67 _ZN7Crasher11doSomethingEv + 71 5 segfault 0x000000010d0a9880 _Z5crashPv + 32 6 segfault 0x000000010d0a9ac7 _Z7goCrashv + 199 7 segfault 0x000000010d0a9b33 main + 67 8 segfault 0x000000010d0a9854 start + 52
crash()
, what will the program output? Where does it crash? Ahem! That's a function! That's a private function! myPrivateInteger == 1752392050 myPrivateDoubles[1] == 60993401604041306737928347282702617388988841504491171140800281285302442927306116721201046092641903128620672849302937378251940003901836219046866981678295779355600933772275817062376375849852470059862498765690530537583237171035779906888043337758015488.000000 myPrivateString == 0x63202c6f6c6c6548 That's a function! 0 segfault 0x0000000109a5e8c8 _Z13reportTroublev + 40 1 segfault 0x0000000109a5e9d0 _Z10catchCrashi + 16 2 libsystem_c.dylib 0x00007fff99b5dcfa _sigtramp + 26 3 ??? 0x0000040000000000 0x0 + 4398046511104 4 segfault 0x0000000109a5ec67 _ZN7Crasher11doSomethingEv + 71 5 segfault 0x0000000109a5ec1a _ZN7Crasher18doSomethingPrivateEv + 208 6 segfault 0x0000000109a5ec67 _ZN7Crasher11doSomethingEv + 71 7 segfault 0x0000000109a5e880 _Z5crashPv + 32 8 segfault 0x0000000109a5eac4 _Z7goCrashv + 196 9 segfault 0x0000000109a5eb33 main + 67 10 segfault 0x0000000109a5e854 start + 52
doSomethingPrivate()
, and the first one went off with a bang, although it didn’t bring us anything that was intended.this
not used, namely in it we have garbage. In the second example (without a shift), a private function is called with this
' om pointing to our string, and our class variables will point to parts of this string and contain, respectively, any garbage included in it. And in the first case, the pointer is likely to simply refer to the memory area inaccessible to the program, so the first call to the private function will be painted.Source: https://habr.com/ru/post/147280/
All Articles