test_crash.cpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. #include "AutoDmp.h"
  2. #include <iostream>
  3. #include <thread>
  4. #include <chrono>
  5. #include <vector>
  6. #include <memory>
  7. #include <cstdlib>
  8. #include <unistd.h>
  9. // Linux崩溃测试用例类
  10. class LinuxCrashTest {
  11. public:
  12. // 段错误测试
  13. static void testSegmentationFault() {
  14. std::cout << "Testing segmentation fault (SIGSEGV)...\n";
  15. int* nullPtr = nullptr;
  16. *nullPtr = 42; // 触发段错误
  17. }
  18. // 除零错误测试
  19. static void testDivisionByZero() {
  20. std::cout << "Testing division by zero (SIGFPE)...\n";
  21. volatile int zero = 0;
  22. volatile int result = 100 / zero; // 触发浮点异常
  23. (void)result; // 避免未使用变量警告
  24. }
  25. // 栈溢出测试
  26. static void testStackOverflow() {
  27. std::cout << "Testing stack overflow (SIGSEGV)...\n";
  28. testStackOverflow(); // 无限递归导致栈溢出
  29. }
  30. // 异常终止测试
  31. static void testAbort() {
  32. std::cout << "Testing abort signal (SIGABRT)...\n";
  33. std::abort(); // 触发 SIGABRT
  34. }
  35. // 非法指令测试
  36. static void testIllegalInstruction() {
  37. std::cout << "Testing illegal instruction (SIGILL)...\n";
  38. // 内联汇编触发非法指令(x86_64)
  39. __asm__("ud2"); // 未定义指令
  40. }
  41. // 总线错误测试
  42. static void testBusError() {
  43. std::cout << "Testing bus error (SIGBUS)...\n";
  44. // 创建一个不对齐的指针访问
  45. char buffer[16];
  46. char* misaligned = buffer + 1;
  47. long* longPtr = reinterpret_cast<long*>(misaligned);
  48. *longPtr = 0x1234567890ABCDEF; // 可能触发总线错误
  49. }
  50. // 数组越界测试
  51. static void testArrayOutOfBounds() {
  52. std::cout << "Testing array out of bounds (SIGSEGV)...\n";
  53. int arr[5] = {1, 2, 3, 4, 5};
  54. // 大量越界访问,最终会触发段错误
  55. for (int i = 0; i < 1000000; ++i) {
  56. arr[i] = i; // 最终会访问到未分配的内存
  57. }
  58. }
  59. // 多线程崩溃测试
  60. static void testMultiThreadCrash() {
  61. std::cout << "Testing multi-thread crash (SIGSEGV)...\n";
  62. auto crashFunc = []() {
  63. std::this_thread::sleep_for(std::chrono::milliseconds(100));
  64. std::cout << " Thread " << std::this_thread::get_id() << " about to crash...\n";
  65. int* p = nullptr;
  66. *p = 123; // 在子线程中崩溃
  67. };
  68. std::thread t(crashFunc);
  69. t.join();
  70. }
  71. // 管道错误测试
  72. static void testPipeError() {
  73. std::cout << "Testing pipe error (SIGPIPE)...\n";
  74. int pipefd[2];
  75. if (pipe(pipefd) == 0) {
  76. close(pipefd[0]); // 关闭读端
  77. // 向已关闭的管道写入数据会触发 SIGPIPE
  78. char data[] = "This will trigger SIGPIPE";
  79. write(pipefd[1], data, sizeof(data));
  80. close(pipefd[1]);
  81. }
  82. }
  83. // 用户信号测试(不会崩溃程序)
  84. static void testUserSignal() {
  85. std::cout << "Testing user signal (SIGUSR1) - safe test...\n";
  86. raise(SIGUSR1); // 这不会终止程序
  87. }
  88. };
  89. void printUsage() {
  90. std::cout << "\nLinux崩溃测试程序使用说明:\n";
  91. std::cout << "test_crash [选项]\n";
  92. std::cout << "选项:\n";
  93. std::cout << " 1 - 段错误 (SIGSEGV - Segmentation Fault)\n";
  94. std::cout << " 2 - 除零错误 (SIGFPE - Floating Point Exception)\n";
  95. std::cout << " 3 - 栈溢出 (SIGSEGV - Stack Overflow)\n";
  96. std::cout << " 4 - 异常终止 (SIGABRT - Abort)\n";
  97. std::cout << " 5 - 非法指令 (SIGILL - Illegal Instruction)\n";
  98. std::cout << " 6 - 总线错误 (SIGBUS - Bus Error)\n";
  99. std::cout << " 7 - 数组越界 (SIGSEGV - Array Out of Bounds)\n";
  100. std::cout << " 8 - 多线程崩溃 (SIGSEGV - Multi-thread Crash)\n";
  101. std::cout << " 9 - 管道错误 (SIGPIPE - Pipe Error)\n";
  102. std::cout << " 0 - 用户信号测试 (SIGUSR1 - 不会崩溃)\n";
  103. std::cout << " h - 显示此帮助\n";
  104. }
  105. void showConfiguration() {
  106. std::cout << "\n=== Linux崩溃处理配置演示 ===\n";
  107. // 创建自定义配置
  108. CrashConfig config;
  109. config.enableCoreDump = true;
  110. config.enableConsoleOutput = true;
  111. config.enableLogFile = true;
  112. config.enableBacktrace = true;
  113. config.crashDirectory = "./crashes";
  114. config.maxCrashFiles = 5;
  115. config.maxBacktraceDepth = 64;
  116. config.enableSymbols = true;
  117. config.enableDetailedInfo = true;
  118. config.asyncSafeOnly = false; // 允许详细日志
  119. std::cout << "崩溃处理器配置:\n";
  120. std::cout << "- 启用core dump: " << (config.enableCoreDump ? "是" : "否") << "\n";
  121. std::cout << "- 启用控制台输出: " << (config.enableConsoleOutput ? "是" : "否") << "\n";
  122. std::cout << "- 启用日志文件: " << (config.enableLogFile ? "是" : "否") << "\n";
  123. std::cout << "- 启用调用栈: " << (config.enableBacktrace ? "是" : "否") << "\n";
  124. std::cout << "- 崩溃目录: " << config.crashDirectory << "\n";
  125. std::cout << "- 最大文件数: " << config.maxCrashFiles << "\n";
  126. std::cout << "- 调用栈深度: " << config.maxBacktraceDepth << "\n";
  127. std::cout << "- 详细信息: " << (config.enableDetailedInfo ? "是" : "否") << "\n";
  128. return;
  129. }
  130. void showSupportedSignals() {
  131. std::cout << "\n=== 支持的Linux信号 ===\n";
  132. const int* signals = AutoDmp::getSupportedSignals();
  133. size_t count = AutoDmp::getSupportedSignalCount();
  134. for (size_t i = 0; i < count; ++i) {
  135. std::cout << "- " << signals[i] << ": ";
  136. switch (signals[i]) {
  137. case SIGSEGV: std::cout << "SIGSEGV (段错误)"; break;
  138. case SIGABRT: std::cout << "SIGABRT (异常终止)"; break;
  139. case SIGFPE: std::cout << "SIGFPE (浮点异常)"; break;
  140. case SIGILL: std::cout << "SIGILL (非法指令)"; break;
  141. case SIGBUS: std::cout << "SIGBUS (总线错误)"; break;
  142. case SIGSYS: std::cout << "SIGSYS (系统调用错误)"; break;
  143. case SIGPIPE: std::cout << "SIGPIPE (管道错误)"; break;
  144. case SIGQUIT: std::cout << "SIGQUIT (退出信号)"; break;
  145. default: std::cout << "Unknown"; break;
  146. }
  147. std::cout << "\n";
  148. }
  149. }
  150. void interactiveMode() {
  151. showConfiguration();
  152. showSupportedSignals();
  153. std::cout << "\n请选择测试类型:\n";
  154. printUsage();
  155. int choice;
  156. std::cout << "\n请输入选择: ";
  157. std::cin >> choice;
  158. if (choice < 0 || choice > 9) {
  159. std::cout << "无效选择\n";
  160. return;
  161. }
  162. std::cout << "\n正在执行测试,3秒后开始...\n";
  163. for (int i = 3; i > 0; --i) {
  164. std::cout << i << "... " << std::flush;
  165. std::this_thread::sleep_for(std::chrono::seconds(1));
  166. }
  167. std::cout << "\n开始测试!\n";
  168. try {
  169. switch (choice) {
  170. case 0:
  171. LinuxCrashTest::testUserSignal();
  172. break;
  173. case 1:
  174. LinuxCrashTest::testSegmentationFault();
  175. break;
  176. case 2:
  177. LinuxCrashTest::testDivisionByZero();
  178. break;
  179. case 3:
  180. LinuxCrashTest::testStackOverflow();
  181. break;
  182. case 4:
  183. LinuxCrashTest::testAbort();
  184. break;
  185. case 5:
  186. LinuxCrashTest::testIllegalInstruction();
  187. break;
  188. case 6:
  189. LinuxCrashTest::testBusError();
  190. break;
  191. case 7:
  192. LinuxCrashTest::testArrayOutOfBounds();
  193. break;
  194. case 8:
  195. LinuxCrashTest::testMultiThreadCrash();
  196. break;
  197. case 9:
  198. LinuxCrashTest::testPipeError();
  199. break;
  200. }
  201. } catch (const std::exception& e) {
  202. std::cout << "捕获到异常: " << e.what() << "\n";
  203. }
  204. std::cout << "\n如果程序能执行到这里,说明测试没有触发预期的崩溃\n";
  205. }
  206. int main(int argc, char* argv[]) {
  207. std::cout << "AutoDmp Linux崩溃检测测试程序\n";
  208. std::cout << "================================\n";
  209. // 创建Linux专用配置
  210. CrashConfig config;
  211. config.enableCoreDump = true;
  212. config.enableConsoleOutput = true;
  213. config.enableLogFile = true;
  214. config.enableBacktrace = true;
  215. config.enableDetailedInfo = true;
  216. config.crashDirectory = "./crashes";
  217. config.maxCrashFiles = 10;
  218. config.maxBacktraceDepth = 128;
  219. config.asyncSafeOnly = false; // 允许详细日志记录
  220. std::cout << "\n=== 启用Linux崩溃处理 ===\n";
  221. std::cout << "使用自定义配置启用崩溃检测...\n";
  222. // 使用配置启用崩溃处理
  223. ENABLE_CRASH_HANDLER_WITH_CONFIG(config);
  224. std::cout << "✓ Linux崩溃处理器已启用\n";
  225. std::cout << "✓ Core dump已启用 (ulimit -c unlimited)\n";
  226. std::cout << "✓ 调用栈跟踪已启用\n";
  227. std::cout << "✓ 异步安全输出已启用\n";
  228. if (argc > 1) {
  229. // 命令行模式
  230. int testType = std::atoi(argv[1]);
  231. std::cout << "\n命令行模式: 测试类型 " << testType << "\n";
  232. switch (testType) {
  233. case 0: LinuxCrashTest::testUserSignal(); break;
  234. case 1: LinuxCrashTest::testSegmentationFault(); break;
  235. case 2: LinuxCrashTest::testDivisionByZero(); break;
  236. case 3: LinuxCrashTest::testStackOverflow(); break;
  237. case 4: LinuxCrashTest::testAbort(); break;
  238. case 5: LinuxCrashTest::testIllegalInstruction(); break;
  239. case 6: LinuxCrashTest::testBusError(); break;
  240. case 7: LinuxCrashTest::testArrayOutOfBounds(); break;
  241. case 8: LinuxCrashTest::testMultiThreadCrash(); break;
  242. case 9: LinuxCrashTest::testPipeError(); break;
  243. default:
  244. std::cout << "无效的测试类型\n";
  245. printUsage();
  246. return 1;
  247. }
  248. } else {
  249. // 交互模式
  250. interactiveMode();
  251. }
  252. return 0;
  253. }