The dbghelp solution is complicated and slow, but it is not too bad for trace applications.
The principle is dbghelp. lib, dbghelp. H provides a lot of information about the current call stack (ESP, EBP), and works with the PDB file of the corresponding module to obtain the current call module (DLL), call functions, call lines, and commands.
The specific principle is no longer nonsense. There are also many documents on the use of dbghelp on the Internet. I will post a few references:
Howto: Dump call stack
Implementation of a debugger (5) debugging symbols
Using dbghelp to obtain the function call Stack: inline assembly (inline assembly) Method
Let's talk about the implementation principle:
We can still intercept new, but do not need to provide a special version of New. just hijack Global New.
After each new call, you can use the dbghelp function to obtain the current call stack and remove the stacks from new to tracer (just put the top several stacks away. Specifically, You can discard a few, depending on the implementation, my implementation starts to call three layers from new, so I just need to discard three layers. you can do it yourself ).
Create a hash and the key is still the allocated memory address. Here, there is an optimization solution for the value. Because the callstack is large, if the current callstack needs to be stored every time, the tracer occupies too much memory. However, although the newProgramIt can be called millions or tens of thousands of times, but the number of call stacks in the place where new is located is limited, and the number of calls stacks may be tens of thousands or tens of thousands. Therefore, once the call stack is obtained, we can first cache the call stack to a vector and calculate the CRC value to another map. Then, the hash value only needs to save the current CALL
Stack ID.
After obtaining the callstack, calculate the CRC value and check it in the map. If there is a corresponding call stack, use the corresponding call stack. Otherwise, generate a new one, in this way, the space is optimized.
The others are the same as the previous tracer. In the delete operation, the records of corresponding addresses are removed from the tracer table. After the program is completed, check whether the hash is cleared. If it is not cleared, dump.
Dbghelp is also required for dump.
Because this implementation needs to hijack the original void * operator new (size_t insize) of C ++, so, as described in the previous chapter, all hash and vector operations must use the Allocator provided by Alibaba to cancel the tracer function. In the implementation process of tracemalloc, if there are other calls to operator new and new, they also need to be eliminated.
Dbghelp is not very thorough in understanding this part, so I won't make any comments.Code, Please spray it lightly ~.