Chạy một ứng dụng trong GDB cho đến khi một ngoại lệ xảy ra


102

Tôi đang làm việc trên một ứng dụng đa luồng và tôi muốn gỡ lỗi nó bằng GDB.

Vấn đề là, một trong những chuỗi của tôi tiếp tục chết với thông báo:

pure virtual method called
terminate called without an active exception
Abort

Tôi biết nguyên nhân của thông báo đó, nhưng tôi không biết nó xảy ra ở đâu trong chuỗi của tôi. Một dấu vết sẽ thực sự hữu ích.

Khi tôi chạy ứng dụng của mình trong GDB, ứng dụng sẽ tạm dừng mỗi khi một chuỗi bị tạm ngừng hoặc tiếp tục. Tôi muốn ứng dụng của mình tiếp tục chạy bình thường cho đến khi một trong các luồng bị chết với ngoại lệ đó, tại thời điểm đó, mọi thứ sẽ tạm dừng để tôi có thể nhận được dấu vết.


Tín hiệu nào đang báo cáo GDB khi nó tạm dừng? bạn sẽ có thể để chạy một lệnh nhưhandle SIGUSR1 pass noprint nostop
Hasturkun

Câu trả lời:


147

Bạn có thể thử sử dụng "điểm bắt đầu" ( catch throw) để dừng trình gỡ lỗi tại điểm mà ngoại lệ được tạo.

Đoạn trích sau Từ hướng dẫn sử dụng gdb mô tả tính năng điểm bắt.


5.1.3 Thiết lập các điểm bắt

Bạn có thể sử dụng các điểm bắt để khiến trình gỡ lỗi dừng đối với một số loại sự kiện chương trình, chẳng hạn như ngoại lệ C ++ hoặc tải thư viện được chia sẻ. Sử dụng lệnh catch để thiết lập điểm bắt.

  • bắt sự kiện

    Dừng khi sự kiện xảy ra. sự kiện có thể là bất kỳ trường hợp nào sau đây:

    • phi

      Việc ném một ngoại lệ C ++.

    • nắm lấy

      Bắt một ngoại lệ C ++.

    • người thực thi

      Một cuộc gọi tới người thực thi. Điều này hiện chỉ khả dụng cho HP-UX.

    • cái nĩa

      Một cuộc gọi đến ngã ba. Điều này hiện chỉ khả dụng cho HP-UX.

    • vfork

      Một cuộc gọi đến vfork. Điều này hiện chỉ khả dụng cho HP-UX.

    • tải hoặc tải libname

      Tải động của bất kỳ thư viện được chia sẻ nào hoặc tải libname của thư viện. Điều này hiện chỉ khả dụng cho HP-UX.

    • dỡ bỏ hoặc dỡ bỏ libname

      Việc dỡ bỏ bất kỳ thư viện chia sẻ nào được tải động hoặc dỡ bỏ thư viện libname. Điều này hiện chỉ khả dụng cho HP-UX.

  • sự kiện tcatch

    Đặt một điểm dừng chỉ được bật cho một điểm dừng. Điểm bắt sẽ tự động bị xóa sau lần đầu tiên bắt được sự kiện.

Sử dụng info breaklệnh để liệt kê các điểm bắt hiện tại.

Hiện tại có một số hạn chế đối với việc xử lý ngoại lệ C ++ (bắt ném và bắt bắt) trong GDB:

  • Nếu bạn gọi một hàm theo cách tương tác, GDB thường trả lại quyền điều khiển cho bạn khi hàm đã hoàn tất thực thi. Tuy nhiên, nếu cuộc gọi tạo ra một ngoại lệ, cuộc gọi có thể bỏ qua cơ chế trả lại quyền kiểm soát cho bạn và khiến chương trình của bạn bị hủy hoặc đơn giản là tiếp tục chạy cho đến khi nó chạm điểm ngắt, bắt được tín hiệu GDB đang lắng nghe hoặc thoát ra. Đây là trường hợp ngay cả khi bạn đặt điểm bắt cho ngoại lệ; các điểm truy cập ngoại lệ bị vô hiệu hóa trong các cuộc gọi tương tác.

  • Bạn không thể nêu ra một ngoại lệ một cách tương tác.

  • Bạn không thể cài đặt một trình xử lý ngoại lệ một cách tương tác.

Đôi khi, catch không phải là cách tốt nhất để gỡ lỗi việc xử lý ngoại lệ: nếu bạn cần biết chính xác vị trí xuất hiện ngoại lệ, tốt hơn hết bạn nên dừng lại trước khi trình xử lý ngoại lệ được gọi, vì bằng cách đó bạn có thể thấy ngăn xếp trước khi bất kỳ thao tác gỡ nào diễn ra. Thay vào đó, nếu bạn đặt một điểm ngắt trong một trình xử lý ngoại lệ, có thể không dễ dàng tìm ra nơi mà ngoại lệ được đưa ra.

Để dừng ngay trước khi một trình xử lý ngoại lệ được gọi, bạn cần một số kiến ​​thức về việc triển khai. Trong trường hợp GNU C ++, các ngoại lệ được đưa ra bằng cách gọi một hàm thư viện có tên __raise_exception có giao diện ANSI C sau:

/* addr is where the exception identifier is stored.
   id is the exception identifier.  */
void __raise_exception (void **addr, void *id);

Để làm cho trình gỡ lỗi nắm bắt tất cả các ngoại lệ trước khi bất kỳ quá trình gỡ ngăn xếp nào diễn ra, hãy đặt một điểm ngắt trên __raise_exception (xem phần Breakpoints; watchpoints; và các ngoại lệ).

Với một điểm ngắt có điều kiện (xem phần Điều kiện ngắt) phụ thuộc vào giá trị của id, bạn có thể dừng chương trình của mình khi một ngoại lệ cụ thể được nâng lên. Bạn có thể sử dụng nhiều điểm ngắt có điều kiện để dừng chương trình của mình khi bất kỳ trường hợp ngoại lệ nào được nâng lên.


Bạn cũng có thể chỉ định loại ngoại lệ để bắt, ví dụ catch throw std::runtime_exception.
scai

5

Đặt điểm ngắt trên __pure_virtual


Trong câu trả lời @JeffreyHill, nó được gọi là __cxa_pure_virtual. Tôi không biết làm thế nào để tự kiểm tra điều đó, vì vậy tôi không muốn chỉnh sửa câu trả lời. Tôi không có ý định bỏ phiếu, nhưng câu trả lời có thể sai bây giờ và nên được chỉnh sửa bởi một người biết điều gì là đúng.
Philipp Claßen,

5

FWIW, rõ ràng, trong gcc 4.1, tên hàm thích hợp đã thay đổi và người ta phải đặt một điểm ngắt trong hàm này.

__cxa_pure_virtual


0

Chỉ có một bên dưới phù hợp với tôi với gdb 8.3:

break _Unwind_RaiseException

"catch throw" hoặc "break __cxx_throw" không hoạt động với tôi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.