这是一个完美的答案,我一直在寻找一个类似的工具,我发现了一个由 John Panzer 在 1998 年制作的名为 CallMonitor 的工具。这是该工具的输出。是的,它是为 Visual C++ 6.0 制作的,但它可以在 Visual Studio 2019 中运行,根本不需要编辑。
(除了缺少我可以不用的参数。)
适用于Windows !!!
我将代码放在我的个人 github 上用于历史备份。(它还包含我自己构建的已编译调试,因此您可以立即对其进行测试,只需在命令提示符下运行 Test.exe 即可查看结果)。
https://github.com/fatrolls/CallMonitor
这是 test.cpp 代码
// Test driver for CallMon
#include <windows.h>
#include <iostream>
using namespace std;
void child2(bool doThrow)
{
Sleep(5);
if (doThrow) throw "random exception";
}
void child1(bool doThrow)
{
child2(false);
child2(doThrow);
}
// Waits a bit, then calls a child function
// that might throw an exception
DWORD WINAPI threadFunc(LPVOID param)
{
Sleep(1);
try {
child1(param ? true : false);
} catch (char *) {
child1(false);
}
return 0;
}
// Starts argv[1] threads running, of which argv[2] throw
// exceptions.
void main(int argc,char *argv[])
{
if (argc!=3)
{
cout << "Usage: " << argv[0] << " <number of threads, or 0> <number of exceptions>" << endl;
cout << " Pass 0 for number of threads for simple nonthreaded test" << endl;
cout << " Pass the number of threads which should throw exceptions as the second arg" << endl;
cout << " Note: The test output for the multithreaded case gives " << endl;
cout << " nearly unreadable output." << endl;
return;
}
const int MAX_THREADS=MAXIMUM_WAIT_OBJECTS;
DWORD id;
HANDLE th[MAX_THREADS];
int numThreads = atol(argv[1]);
int numExc = atol(argv[2]);
if (numThreads == 0)
{
threadFunc((void*)(numExc));
}
else
{
int i;
for(i=0;i<numThreads;i++)
{
void * param= (void*)(i < numExc ? 1 : 0);
th[i] = CreateThread(NULL,0,threadFunc,param,0,&id);
}
WaitForMultipleObjects(numThreads,th,TRUE,50000);
for(i=0;i<numThreads;i++)
{
CloseHandle(th[i]);
}
}
}
这是 Test.exe 0 20 的输出
C:\Users\User\Desktop\callmonitor\Debug>Test 0 20
Test!main (002B2160)
Test!threadFunc (002B20A0)
Test!child1 (002B1F70)
Test!child2 (002B1FB0)
exit 002B1FB0, elapsed time=4 ms (13738100 ticks)
Test!child2 (002B1FB0)
Test!child1 (002B1F70)
Test!child2 (002B1FB0)
exit 002B1FB0, elapsed time=4 ms (123855
75 ticks)
Test!child2 (002B1FB0)
exit 002B1FB0, elapsed time=5 ms (150199
75 ticks)
exit 002B1F70, elapsed time=27 ms (82797408 tick
s)
exception exit 002B1FB0, elapsed time=40 ms (122291193 t
icks)
exception exit 002B1F70, elapsed time=56 ms (170411060 ticks)
exit 002B20A0, elapsed time=61 ms (184553835 ticks)
exit 002B2160, elapsed time=74 ms (222897953 ticks)
C:\Users\User\Desktop\callmonitor\Debug>
这是Test.exe的输出
Test!main (01132160)
Test!std::operator<<<std::char_traits<char> > (01131740)
Test!<unknown symbol> (01132070)
exit 01132070, elapsed time=0 ms (1960 ticks)
Test!<unknown symbol> (01131CB0)
Test!<unknown symbol> (01131C40)
exit 01131C40, elapsed time=0 ms (3123 ticks)
exit 01131CB0, elapsed time=2 ms (7502464 ticks)
Test!<unknown symbol> (01131F00)
exit 01131F00, elapsed time=0 ms (378 ticks)
Usage: Test!<unknown symbol> (01131E60)
Test!<unknown symbol> (01131DC0)
exit 01131DC0, elapsed time=0 ms (1740 ticks)
exit 01131E60, elapsed time=2 ms (6846975 ticks)
exit 01131740, elapsed time=15 ms (47014729 ticks)
Test!std::operator<<<std::char_traits<char> > (01131740)
Test!<unknown symbol> (01132070)
exit 01132070, elapsed time=0 ms (1485 ticks)
Test!<unknown symbol> (01131CB0)
Test!<unknown symbol> (01131C40)
exit 01131C40, elapsed time=0 ms (2268 ticks)
exit 01131CB0, elapsed time=2 ms (8479308 ticks)
Test!<unknown symbol> (01131F00)
exit 01131F00, elapsed time=0 ms (285 ticks)
Test Test!<unknown symbol> (01131E60)
Test!<unknown symbol> (01131DC0)
exit 01131DC0, elapsed time=0 ms (2415 ticks)
exit 01131E60, elapsed time=3 ms (10897188 ticks)
exit 01131740, elapsed time=17 ms (52439945 ticks)
Test!std::operator<<<std::char_traits<char> > (01131740)
Test!<unknown symbol> (01132070)
exit 01132070, elapsed time=0 ms (1443 ticks)
Test!<unknown symbol> (01131CB0)
Test!<unknown symbol> (01131C40)
exit 01131C40, elapsed time=0 ms (2550 ticks)
exit 01131CB0, elapsed time=2 ms (8731260 ticks)
Test!<unknown symbol> (01131F00)
exit 01131F00, elapsed time=0 ms (354 ticks)
<number of threads, or 0> <number of exceptions> Test!<unknown sy
mbol> (01131E60)
Test!<unknown symbol> (01131DC0)
exit 01131DC0, elapsed time=0 ms (2397 ticks)
exit 01131E60, elapsed time=3 ms (10455030 ticks)
exit 01131740, elapsed time=18 ms (54133983 ticks)
Test!std::endl<char,std::char_traits<char> > (01131BE0)
exit 01131BE0, elapsed time=0 ms (1256316 ticks)
Test!std::operator<<<std::char_traits<char> > (01131740)
Test!<unknown symbol> (01132070)
exit 01132070, elapsed time=0 ms (1554 ticks)
Test!<unknown symbol> (01131CB0)
Test!<unknown symbol> (01131C40)
exit 01131C40, elapsed time=0 ms (1983 ticks)
exit 01131CB0, elapsed time=2 ms (8839671 ticks)
Test!<unknown symbol> (01131F00)
exit 01131F00, elapsed time=0 ms (2736 ticks)
Pass 0 for number of threads for simple nonthreaded test Test!<un
known symbol> (01131E60)
Test!<unknown symbol> (01131DC0)
exit 01131DC0, elapsed time=0 ms (1605 ticks)
exit 01131E60, elapsed time=2 ms (8375898 ticks)
exit 01131740, elapsed time=20 ms (61957080 ticks)
Test!std::endl<char,std::char_traits<char> > (01131BE0)
exit 01131BE0, elapsed time=0 ms (1303008 ticks)
Test!std::operator<<<std::char_traits<char> > (01131740)
Test!<unknown symbol> (01132070)
exit 01132070, elapsed time=0 ms (1245 ticks)
Test!<unknown symbol> (01131CB0)
Test!<unknown symbol> (01131C40)
exit 01131C40, elapsed time=0 ms (1548 ticks)
exit 01131CB0, elapsed time=2 ms (8249352 ticks)
Test!<unknown symbol> (01131F00)
exit 01131F00, elapsed time=0 ms (408 ticks)
Pass the number of threads which should throw exceptions as the second arg
Test!<unknown symbol> (01131E60)
Test!<unknown symbol> (01131DC0)
exit 01131DC0, elapsed time=0 ms (1503 ticks)
exit 01131E60, elapsed time=2 ms (8074389 ticks)
exit 01131740, elapsed time=17 ms (52143870 ticks)
Test!std::endl<char,std::char_traits<char> > (01131BE0)
exit 01131BE0, elapsed time=0 ms (1312485 ticks)
Test!std::operator<<<std::char_traits<char> > (01131740)
Test!<unknown symbol> (01132070)
exit 01132070, elapsed time=0 ms (1392 ticks)
Test!<unknown symbol> (01131CB0)
Test!<unknown symbol> (01131C40)
exit 01131C40, elapsed time=0 ms (2043 ticks)
exit 01131CB0, elapsed time=2 ms (8364006 ticks)
Test!<unknown symbol> (01131F00)
exit 01131F00, elapsed time=0 ms (357 ticks)
Note: The test output for the multithreaded case gives Test!<un
known symbol> (01131E60)
Test!<unknown symbol> (01131DC0)
exit 01131DC0, elapsed time=0 ms (1557 ticks)
exit 01131E60, elapsed time=2 ms (8433210 ticks)
exit 01131740, elapsed time=17 ms (51733404 ticks)
Test!std::endl<char,std::char_traits<char> > (01131BE0)
exit 01131BE0, elapsed time=0 ms (1323972 ticks)
Test!std::operator<<<std::char_traits<char> > (01131740)
Test!<unknown symbol> (01132070)
exit 01132070, elapsed time=0 ms (1257 ticks)
Test!<unknown symbol> (01131CB0)
Test!<unknown symbol> (01131C40)
exit 01131C40, elapsed time=0 ms (1668 ticks)
exit 01131CB0, elapsed time=2 ms (7994649 ticks)
Test!<unknown symbol> (01131F00)
exit 01131F00, elapsed time=0 ms (393 ticks)
nearly unreadable output. Test!<unknown symbol> (01131E60)
Test!<unknown symbol> (01131DC0)
exit 01131DC0, elapsed time=0 ms (1572 ticks)
exit 01131E60, elapsed time=2 ms (8090115 ticks)
exit 01131740, elapsed time=17 ms (52094652 ticks)
Test!std::endl<char,std::char_traits<char> > (01131BE0)
exit 01131BE0, elapsed time=0 ms (1355601 ticks)
exit 01132160, elapsed time=162 ms (486552183 ticks)