2012-10-03 33 views
14

Để đặt nhẹ nhàng, tôi có vấn đề về bộ nhớ nhỏ và đang hết công cụ và ý tưởng để tách biệt nguyên nhân.Các công cụ để cô lập lỗi đập ngăn xếp

Tôi có một chương trình C/C++ đa luồng (đa luồng) đã phát triển một sự cố ngăn xếp theo các biên dịch tối ưu hóa với GCC sau 4.4.4 và trước 4.7.1.

Triệu chứng là trong khi tạo một trong các chủ đề, tôi nhận được một ngăn xếp đầy đủ, không chỉ RIP, nhưng tất cả các khung cha và hầu hết các thanh ghi là 0x00 hoặc địa chỉ không có ý nghĩa khác. Chủ đề nào gây ra vấn đề dường như là ngẫu nhiên, tuy nhiên việc đánh giá bằng các thông điệp tường trình có vẻ như được tách biệt với cùng một đoạn mã, và dường như có một điểm bán lặp lại trong quá trình tạo chuỗi mới. Điều này đã làm cho nó rất khó để bẫy và cô lập mã vi phạm hẹp hơn so với một đơn vị biên dịch duy nhất của hàng ngàn dòng, vì print() trong tập tin vi phạm cho đến nay tỏ ra không đáng tin cậy khi cố gắng thu hẹp xuống phần hoạt động.

Việc tạo chủ đề dẫn tắt các chủ đề mà cuối cùng đập vỡ chồng là:


extern "C" 
{ 
static ThreadReturnVal ThreadAPI WriterThread(void *act) 
{ 
    Recorder  *rec = reinterpret_cast (act); 
    xuint64  writebytes; 
    LoggerHandle m_logger = XXGetLogger("WriterThread"); 

    if (SetThreadAffinity(rec->m_cpu_mask)) 
    { ... } 
    SetThreadPrio((xint32)rec->m_thread_priority); 

    while (true) 
    { 
    ... poll a ring buffer ... Hard Spin 100% use on a single core, this is that sort of crazy code. 
    } 
} 

Tôi đã thử một debug xây dựng, nhưng các triệu chứng chỉ xuất hiện trong tối ưu hóa xây dựng, -O2 hoặc tốt hơn. Tôi đã thử Valgrind/memcheck và DRD nhưng cả hai không tìm thấy bất kỳ vấn đề trước khi ngăn xếp được thổi đi (và mất khoảng 12hr để đạt được sự thất bại)

Một biên dịch với -O2 -Wstack-bảo vệ thấy không có gì sai, tuy nhiên một bản xây dựng với -fstack-protector-tất cả đều bảo vệ tôi khỏi lỗi, nhưng phát ra không có lỗi.

Hàng rào điện cũng bẫy, nhưng chỉ sau khi ngăn xếp hết.

Câu hỏi: Các công cụ hoặc kỹ thuật nào khác hữu ích trong việc thu hẹp phần vi phạm?

Rất cám ơn, --Bill

+0

OK. Tôi sẽ cắn ... ngăn xếp nào bị đập vỡ? –

+1

Nếu đó là ngăn xếp của chuỗi tạo, một số mã có thể đẹp - bạn đang chuyển các tham số nào cho chuỗi mới/s? –

+2

Chỉ cần cho rõ ràng, là bạn nói rằng nó hoạt động tốt trên g ++ 4.4.2 và 4.8 hoặc rằng những phiên bản đã không được thử nghiệm? –

Trả lời

4

Một vài lựa chọn để tiếp cận loại sự cố này:

Bạn có thể thử thiết lập một breakpoint phần cứng trên một địa chỉ ngăn xếp trước khi tham nhũng xảy ra và hy vọng phá vỡ debugger đủ sớm trong tham nhũng để cung cấp một gỡ lỗi mơ hồ hữu ích tiểu bang. Phần khó khăn ở đây là chọn địa chỉ ngăn xếp phải; tùy thuộc vào cách ngẫu nhiên 'lựa chọn' của chuỗi vi phạm là điều này có thể không thực tế. Nhưng từ một trong những nhận xét của bạn, có vẻ như nó thường là chuỗi mới được tạo ra bị đập vỡ, vì vậy điều này có thể là doable. Cố gắng phá vỡ trong quá trình tạo chuỗi, lấy vị trí ngăn xếp của luồng, bù lại bằng một số phỏng đoán hoang dã, đặt BP phần cứng và tiếp tục. Dựa vào việc bạn có nghỉ ngơi quá sớm, quá muộn hay không, hãy điều chỉnh bù đắp, rửa sạch và lặp lại. Đây là cơ bản đoán và kiểm tra tiên tiến, và có thể bị cản trở hoặc hoàn toàn không thực tế nếu mô hình tham nhũng quá ngẫu nhiên, nhưng điều ngạc nhiên là mức độ thường xuyên này có thể dẫn đến ngăn xếp dễ đọc và nỗ lực gỡ lỗi thành công.

Một tùy chọn khác là bắt đầu thu thập các bãi rác.Cố gắng tìm kiếm các mẫu giữa các bãi tai nạn có thể giúp đưa bạn đến gần nguồn gốc của tham nhũng. Có lẽ bạn sẽ nhận được may mắn và một trong những bãi sụp đổ sẽ sụp đổ 'nhanh hơn'/'gần gũi hơn với nguồn'.

Thật không may, cả hai kỹ thuật này đều mang tính nghệ thuật cao hơn về khoa học; chúng không mang tính quyết định, dựa vào liều lượng may mắn, v.v. (ít nhất là trong kinh nghiệm của tôi .. mà đang được nói, có những người ngoài kia có thể làm những điều tuyệt vời với bãi đổ vỡ, nhưng phải mất rất nhiều thời gian để đạt đến cấp độ kỹ năng đó).

Một lưu ý khác: như những người khác đã chỉ ra, bộ nhớ uninitialized là một nguồn rất điển hình của gỡ lỗi vs sự khác biệt phát hành, và có thể dễ dàng là vấn đề của bạn ở đây. Tuy nhiên, một khả năng khác để ghi nhớ là sự khác biệt về thời gian. Thứ tự mà các chủ đề được lên kế hoạch trong và trong bao lâu, thường khác nhau đáng kể trong gỡ lỗi và phát hành, và có thể dễ dàng dẫn đến các lỗi đồng bộ hóa được che giấu trong một nhưng không phải là khác. Những khác biệt này có thể chỉ là do sự khác biệt về tốc độ thực thi, nhưng tôi nghĩ rằng một số runtimes cố ý gây rối với lập lịch trình luồng trong một môi trường gỡ lỗi.

+0

Cảm ơn tất cả các câu trả lời và đầu vào của bạn, tôi chấp nhận điều này như là câu trả lời, nhưng nếu bạn có nhiều ý tưởng hay suy nghĩ tôi sẽ chào đón nhiều đầu vào hơn vì tôi tiếp tục đẩy về phía trước để cố gắng tách biệt lỗi này. –

+0

Tôi quên đề cập đến, nhưng một thủ thuật khác mà tôi đã thấy hữu ích cho các loại vấn đề này, nếu cơ sở mã cho phép: thay đổi số lượng chủ đề tối đa. Có số lượng chủ đề đồng thời tối thiểu cần thiết để kiểm soát lại lỗi một cách đáng tin cậy thường dẫn đến bối cảnh gỡ lỗi thân thiện hơn. Lý tưởng nhất, bạn có thể mang nó xuống hai chủ đề (hoặc đôi khi, bạn tìm ra nó repros với một sợi và thậm chí không thực sự là một lỗi synchro, luôn luôn tốt để loại trừ điều này). – WeirdlyCheezy

2

Bạn có thể sử dụng một công cụ phân tích tĩnh để kiểm tra một số lỗi sutble, có lẽ một trong những lỗi được tìm thấy sẽ là nguyên nhân gây ra lỗi của bạn. Bạn có thể tìm thấy một số thông tin về các công cụ này here.

+0

Điểm tốt, tôi đã không được coi là Lint vv để cố gắng tìm thấy điều này. –

Các vấn đề liên quan