Linux下gdb attach的使用(調試已在運行的進程)


在Linux上,執行有多線程的程序時,當程序執行退出操作時有時會遇到卡死現象,如果程序模塊多,代碼量大,很難快速定位,此時可試試gdb attach方法。

測試代碼main.cpp如下,這里為了使程序退出時產生卡死現象,在第51行時push線程sleep 100分鍾:


   
   
  
  
          
  1. #include <stdio.h>
  2. #include <thread>
  3. #include <queue>
  4. #include <mutex>
  5. #include <condition_variable>
  6. #include <chrono>
  7. namespace {
  8. class Queue {
  9. public:
  10. Queue() = default;
  11. ~Queue() { }
  12. void Init(int num) {
  13. for ( int i = 0; i < num; ++i) {
  14. queue_.push(i);
  15. }
  16. }
  17. int Pop() {
  18. std::unique_lock<std::mutex> lck(mutex_);
  19. while (queue_.size() == 0) {
  20. cv_.wait(lck);
  21. }
  22. int value = queue_.front();
  23. queue_.pop();
  24. return value;
  25. }
  26. void Push(int value) {
  27. std::unique_lock<std::mutex> lck(mutex_);
  28. queue_.push(value);
  29. cv_.notify_all();
  30. }
  31. private:
  32. std:: queue< int> queue_;
  33. std::mutex mutex_;
  34. std::condition_variable cv_;
  35. }; // class Queue
  36. bool running = false;
  37. void push(Queue& q) {
  38. int value = 100;
  39. while (running) {
  40. q.Push(value++);
  41. std::this_thread::sleep_for( std::chrono::minutes( 100));
  42. }
  43. }
  44. void pop(Queue& q) {
  45. while (running) {
  46. fprintf( stdout, "pop value: %d\n", q.Pop());
  47. std::this_thread::sleep_for( std::chrono::seconds( 1));
  48. }
  49. }
  50. } // namespace
  51. int main()
  52. {
  53. fprintf( stdout, "test start\n");
  54. Queue q;
  55. q.Init( 2);
  56. running = true;
  57. std::thread th1(push, std::ref(q));
  58. std::thread th2(pop, std::ref(q));
  59. std::this_thread::sleep_for( std::chrono::seconds( 10));
  60. running = false;
  61. th1.join();
  62. th2.join();
  63. fprintf( stdout, "test end\n");
  64. return 0;
  65. }

build.sh腳本內容如下:


   
   
  
  
          
  1. g++ -g -std=c++11 -o main main.cpp -lpthread
  2. ./main

執行:$ ./build.sh ,執行結果如下,程序無法正常退出,產生卡死現象:

通過命令:$ ps -aux | grep main ,獲取執行main的進程(pid),如下圖所示,執行main的進程為18786:

啟動gdb attach,執行gdb attach pid即可調試正在運行的程序,執行:$ gdb attach 18786,若執行gdb attach時提示:” ptrace: Operation not permitted”,則執行:$ sudo gdb attach 18786,如下圖所示:

也可執行:$ gdb main 18786,與gdb attach 18786相同。

常用的命令如下:

1. bt:查看函數調用棧的所有信息,當程序執行異常時,可通過此命令查看程序的調用過程;

2. info threads:顯示當前進程中的線程;

3. thread id:切換到具體的線程id,一般切換到具體的線程后再執行bt等操作。

首先執行info threads,發現共有3個線程,當前線程id是1,即主線程,執行bt,會發現程序卡在第77行,即th1.join()語句上,即在push函數內沒有退出;執行thread 2,再執行bt,發現此線程在執行pop函數,卡在了第24行的cv_.wait(lck)語句上;執行thread 3,再執行bt,發現此線程在執行push函數,卡在了第51行的std::this_thread::sleep_for(std::chrono::minutes(100));語句上,分析完成,了解了程序卡死的原因,執行結果如下圖所示:

GitHubhttps://github.com/fengbingchun/Messy_Test


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM