Chương trình chỉ bị treo khi bản phát hành - làm thế nào để gỡ lỗi?


95

Tôi gặp phải loại sự cố "Schroedinger's Cat" ở đây - chương trình của tôi (thực sự là bộ thử nghiệm cho chương trình của tôi, nhưng dù sao cũng là một chương trình) đang gặp sự cố, nhưng chỉ khi được xây dựng ở chế độ phát hành và chỉ khi khởi chạy từ dòng lệnh . Thông qua gỡ lỗi thượng cổ (ví dụ: các thông báo printf () khó chịu ở khắp nơi), tôi đã xác định được phương pháp kiểm tra nơi mã bị lỗi, mặc dù rất tiếc sự cố thực sự dường như xảy ra trong một số trình hủy, vì các thông báo theo dõi cuối cùng mà tôi thấy là trong các trình hủy khác thực thi rõ ràng.

Khi tôi cố gắng chạy chương trình này bên trong Visual Studio, nó không bị lỗi. Tương tự khi khởi chạy từ WinDbg.exe. Sự cố chỉ xảy ra khi khởi chạy từ dòng lệnh. Điều này đang xảy ra trong Windows Vista, btw và rất tiếc là tôi không có quyền truy cập vào máy XP ngay bây giờ để kiểm tra.

Sẽ thực sự tuyệt vời nếu tôi có thể yêu cầu Windows in ra một dấu vết ngăn xếp, hoặc một cái gì đó khác ngoài việc đơn giản là chấm dứt chương trình như thể nó đã thoát sạch. Có ai có bất kỳ lời khuyên nào về cách tôi có thể nhận được một số thông tin có ý nghĩa hơn ở đây và hy vọng sửa lỗi này không?

Chỉnh sửa: Vấn đề thực sự là do một mảng nằm ngoài giới hạn gây ra, mà tôi mô tả nhiều hơn trong bài đăng này . Cảm ơn mọi người đã giúp đỡ của bạn trong việc tìm kiếm vấn đề này!


Bạn có thể cho một mẫu của phương pháp thử nghiệm đó?
akalenuk

Không xin lỗi, mã quá phức tạp để có thể dễ dàng dán vào đây và như tôi đã đề cập, nó không xảy ra trong chính phương thức thử nghiệm mà là một trình hủy sau đó. Tuy nhiên, không có con trỏ chưa khởi tạo hoặc bất kỳ thứ gì tương tự trong phương pháp này.
Nik Reiman 9/10/08

3
Hầu hết các câu trả lời chỉ hơn phỏng đoán. Có một vài kỹ thuật phổ biến để phân tích đâm phát hành xây dựng mà không cần gắn một debugger: stackoverflow.com/a/18513077/214777?stw=2
Sebastian

Câu trả lời:


127

Trong 100% trường hợp tôi đã thấy hoặc nghe nói đến, trong đó một chương trình C hoặc C ++ chạy tốt trong trình gỡ lỗi nhưng không thành công khi chạy bên ngoài, nguyên nhân là do phần cuối của một mảng cục bộ hàm được ghi. (Trình gỡ lỗi đặt nhiều hơn vào ngăn xếp, vì vậy bạn ít có khả năng ghi đè lên thứ gì đó quan trọng.)


31
Ai đó cho người đàn ông này một điếu xì gà! Trong trường hợp của tôi, tôi đã chuyển trong một StringBuilder không có dung lượng đủ lớn cho hàm P / Invoke. Tôi đoán nó giống như ai đó viết lên mặt bạn bằng bút đánh dấu ma thuật khi bạn đang ngủ: dưới trình gỡ lỗi, họ cuối cùng viết nguệch ngoạc trên trán bạn, vì vậy bạn không nhận thấy, nhưng không có trình gỡ lỗi, họ sẽ đâm bạn vào mắt ... đại loại như vậy. Cảm ơn vì mẹo này!
Nicholas Piasecki

1
Trong trường hợp của tôi, hóa ra là một vấn đề về căn chỉnh trên bộ xử lý ARM sử dụng obj-C.
Almo

1
11 năm sau và điều này vẫn đúng ... đừng quên bảo lưu vectơ của bạn.
dav

1
ok, vậy thì làm cách nào để thay đổi hành vi của chế độ gỡ lỗi để người ta có thể thực sự gỡ lỗi.
Paul Childs

1
"Bây giờ biết nơi để xem xét" nhưng làm thế nào tất cả mọi thứ làm việc trong debug cho bạn biết nơi vấn đề là. Mặc dù tôi nghĩ rằng câu trả lời của bạn là đúng trong hầu hết các trường hợp và biết những gì cần tìm là một khởi đầu tốt, nhưng việc tìm kiếm cơ sở mã lớn để xác định chính xác vị trí vấn đề có thể rất tốn kém.
Paul Childs

55

Khi tôi gặp sự cố như thế này trước đây thường là do khởi tạo biến. Trong chế độ gỡ lỗi, các biến và con trỏ được khởi tạo tự động về 0 nhưng ở chế độ phát hành thì không. Do đó, nếu bạn có mã như thế này

int* p;
....
if (p == 0) { // do stuff }

Trong chế độ gỡ lỗi, mã trong if không được thực thi nhưng trong chế độ phát hành p chứa một giá trị không xác định, giá trị này khó có thể là 0, vì vậy mã được thực thi thường gây ra sự cố.

Tôi sẽ kiểm tra mã của bạn để tìm các biến chưa được khởi tạo. Điều này cũng có thể áp dụng cho nội dung của mảng.


Các trường hợp điển hình là quên đặt một biến thành viên vào (một trong) danh sách khởi tạo thành viên của hàm tạo. Có tác dụng tương tự nhưng sẽ khó tìm hơn nếu bạn không biết rằng bạn cũng nên tìm cách khởi tạo thành viên thích hợp.
steffenj

1
Trong chế độ gỡ lỗi, các biến thường được khởi tạo thành một số 'Hằng số do trình biên dịch xác định' có thể được sử dụng trong việc gỡ lỗi để cho biết biến đang ở trạng thái nào. Ví dụ: con trỏ NULL hoặc 0xDeadBeef là phổ biến.
Martin York

Thời gian chạy gỡ lỗi thường khởi tạo bộ nhớ thành một số giá trị khác không, đặc biệt để kiểm tra con trỏ NULL sẽ khiến mã hoạt động như thể con trỏ mà chúng ta không phải là NULL. Nếu không, bạn có mã chạy chính xác trong chế độ gỡ lỗi làm hỏng chế độ phát hành.
Michael Burr

1
Không, các biến hoàn toàn không được khởi tạo và UB vẫn "sử dụng" chúng cho đến khi chúng được gán cho. Tuy nhiên, nội dung bộ nhớ bên dưới thường được điền sẵn 0x0000000 hoặc 0xDEADBEEF hoặc các mẫu dễ nhận biết khác.
Lightness Races in Orbit

26

Cho đến nay chưa có câu trả lời nào cố gắng đưa ra một cái nhìn tổng quan nghiêm túc về các kỹ thuật có sẵn để gỡ lỗi các ứng dụng phát hành:

  1. Các bản dựng Release và Debug hoạt động khác nhau vì nhiều lý do. Đây là một tổng quan tuyệt vời. Mỗi sự khác biệt này có thể gây ra lỗi trong bản phát hành không tồn tại trong bản dựng Gỡ lỗi.

  2. Sự hiện diện của trình gỡ lỗi cũng có thể thay đổi hoạt động của chương trình , cả đối với các bản dựng phát hành và gỡ lỗi. Hãy xem câu trả lời này. Nói tóm lại, ít nhất Visual Studio Debugger sử dụng Debug Heap tự động khi được đính kèm vào một chương trình. Bạn có thể tắt đống gỡ lỗi bằng cách sử dụng biến môi trường _NO_DEBUG_HEAP. Bạn có thể chỉ định điều này trong thuộc tính máy tính của mình hoặc trong Cài đặt dự án trong Visual Studio. Điều đó có thể làm cho sự cố có thể tái tạo được với trình gỡ lỗi được đính kèm.

    Thông tin thêm về gỡ lỗi tham nhũng đống tại đây.

  3. Nếu giải pháp trước đó không hoạt động, bạn cần bắt ngoại lệ chưa được xử lý và đính kèm trình gỡ lỗi sau khám nghiệm tử thi trong trường hợp sự cố xảy ra. Bạn có thể sử dụng ví dụ WinDbg cho việc này, thông tin chi tiết về các trình gỡ lỗi sau giết mổ có sẵn và cài đặt của chúng tại MSDN

  4. Bạn có thể cải thiện mã xử lý ngoại lệ của mình và nếu đây là ứng dụng sản xuất, bạn nên:

    a. Cài đặt trình xử lý chấm dứt tùy chỉnh bằngstd::set_terminate

    Nếu bạn muốn gỡ lỗi cục bộ sự cố này, bạn có thể chạy một vòng lặp vô tận bên trong trình xử lý kết thúc và xuất một số văn bản ra bảng điều khiển để thông báo cho bạn rằng std::terminate đã được gọi. Sau đó, đính kèm trình gỡ lỗi và kiểm tra ngăn xếp cuộc gọi. Hoặc bạn in dấu vết ngăn xếp như được mô tả trong câu trả lời này.

    Trong một ứng dụng sản xuất, bạn có thể muốn gửi báo cáo lỗi về nhà, lý tưởng nhất là cùng với một kết xuất bộ nhớ nhỏ cho phép bạn phân tích vấn đề như được mô tả ở đây.

    b. Sử dụng cơ chế xử lý ngoại lệ có cấu trúc của Microsoft cho phép bạn bắt cả ngoại lệ phần cứng và phần mềm. Xem MSDN . Bạn có thể bảo vệ các phần mã của mình bằng SEH và sử dụng cách tiếp cận tương tự như trong a) để gỡ lỗi vấn đề. SEH cung cấp thêm thông tin về ngoại lệ đã xảy ra mà bạn có thể sử dụng khi gửi báo cáo lỗi từ ứng dụng sản xuất.


16

Những điều cần chú ý:

Mảng ghi đè - trình gỡ lỗi studio trực quan chèn đệm có thể ngăn chặn sự cố.

Điều kiện cuộc đua - bạn có tham gia nhiều chủ đề không nếu như vậy một điều kiện đua nhiều chỉ hiển thị khi một ứng dụng được thực thi trực tiếp.

Liên kết - là phiên bản phát hành của bạn kéo đúng thư viện.

Những điều nên thử:

Minidump - thực sự dễ sử dụng (chỉ cần tra cứu trong msdn) sẽ cung cấp cho bạn một kết xuất sự cố đầy đủ cho mỗi luồng. Bạn chỉ cần tải đầu ra vào studio trực quan và nó giống như thể bạn đang gỡ lỗi tại thời điểm xảy ra sự cố.


1
Xin chào - Tôi đã bỏ phiếu ẩn danh cho câu trả lời này. Tôi muốn hiểu tại sao?
morechilli

12

Bạn có thể đặt WinDbg làm trình gỡ lỗi sau khi chết. Thao tác này sẽ khởi chạy trình gỡ lỗi và đính kèm nó vào quy trình khi sự cố xảy ra. Để cài đặt WinDbg để gỡ lỗi sau khi chết, hãy sử dụng tùy chọn / I (lưu ý nó được viết hoa ):

windbg /I

Thêm chi tiết tại đây .

Về nguyên nhân, rất có thể đó là một biến đơn lẻ như các câu trả lời khác gợi ý.


2
Và đừng quên rằng bạn có thể để trình biên dịch tạo các tệp PDB ngay cả cho các bản dựng phát hành, mặc dù nó không phải là mặc định.
Michael Burr

Câu trả lời thực sự duy nhất cho câu hỏi thực sự.
Sebastian,

10

Sau nhiều giờ gỡ lỗi, cuối cùng tôi đã tìm ra nguyên nhân của sự cố, nguyên nhân thực sự là do tràn bộ đệm, gây ra sự khác biệt byte duy nhất:

char *end = static_cast<char*>(attr->data) + attr->dataSize;

Đây là lỗi cột hàng rào (lỗi từng lỗi một) và đã được khắc phục bằng cách:

char *end = static_cast<char*>(attr->data) + attr->dataSize - 1;

Điều kỳ lạ là, tôi đã đặt một số lệnh gọi tới _CrtCheckMemory () xung quanh các phần khác nhau của mã của tôi và chúng luôn trả về 1. Tôi có thể tìm ra nguồn gốc của vấn đề bằng cách đặt "return false;" các lệnh gọi trong trường hợp thử nghiệm, và sau đó cuối cùng xác định thông qua thử-và-sai ở đâu là lỗi.

Cảm ơn mọi người đã đóng góp ý kiến ​​- hôm nay tôi đã học được rất nhiều về windbg.exe! :)


8
Hôm nay tôi đã gỡ lỗi một vấn đề tương tự và _CrtCheckMemory () luôn trả về 1. Nhưng sau đó tôi nhận ra tại sao: trong chế độ Phát hành, _CrtCheckMemory # được định nghĩa là ((int) 1).
Brian Morearty

7

Mặc dù bạn đã xây dựng exe của mình như một phiên bản phát hành, bạn vẫn có thể tạo các tệp PDB (Cơ sở dữ liệu chương trình) cho phép bạn xếp chồng dấu vết và thực hiện một số lượng hạn chế kiểm tra biến. Trong cài đặt bản dựng của bạn, có một tùy chọn để tạo các tệp PDB. Bật tính năng này và liên kết lại. Sau đó, hãy thử chạy từ IDE trước để xem bạn có gặp sự cố hay không. Nếu vậy, thật tuyệt - bạn đã sẵn sàng để xem xét mọi thứ. Nếu không, thì khi chạy từ dòng lệnh, bạn có thể thực hiện một trong hai điều sau:

  1. Chạy EXE và trước khi xảy ra sự cố, hãy thực hiện Đính kèm vào Quy trình (menu Công cụ trên Visual Studio).
  2. Sau sự cố, hãy chọn tùy chọn để khởi chạy trình gỡ lỗi.

Khi được yêu cầu trỏ đến các tệp PDB, hãy duyệt để tìm chúng. Nếu PDB được đặt trong cùng một thư mục đầu ra với EXE hoặc DLL của bạn, chúng có thể sẽ được chọn tự động.

PDB cung cấp một liên kết đến nguồn với đủ thông tin ký hiệu để có thể thấy dấu vết ngăn xếp, các biến, v.v. Bạn có thể kiểm tra các giá trị như bình thường, nhưng hãy lưu ý rằng bạn có thể đọc sai vì vượt qua tối ưu hóa có thể chỉ có ý nghĩa xuất hiện trong sổ đăng ký hoặc mọi thứ diễn ra theo một thứ tự khác với bạn mong đợi.

NB: Tôi đang giả định một môi trường Windows / Visual Studio ở đây.


3

Những sự cố như thế này hầu như luôn luôn xảy ra vì IDE thường sẽ đặt nội dung của biến chưa được khởi tạo thành số không, giá trị null hoặc một số giá trị 'hợp lý' khác, trong khi khi chạy nguyên bản, bạn sẽ nhận được bất kỳ thứ gì ngẫu nhiên mà hệ thống nhặt được.

Do đó, lỗi của bạn gần như chắc chắn là bạn đang sử dụng thứ gì đó giống như bạn đang sử dụng một con trỏ trước khi nó được khởi tạo đúng cách và bạn đang xử lý nó trong IDE vì nó không trỏ đến bất kỳ đâu nguy hiểm - hoặc giá trị được xử lý bởi kiểm tra lỗi - nhưng ở chế độ phát hành, nó thực hiện một điều gì đó khó chịu.


3

Để có một kết xuất sự cố mà bạn có thể phân tích:

  1. Tạo tệp pdb cho mã của bạn.
  2. Bạn rebase để tải exe và dlls của bạn ở cùng một địa chỉ.
  3. Bật trình gỡ lỗi sau khám nghiệm tử thi chẳng hạn như Dr.Watson
  4. Kiểm tra địa chỉ lỗi sự cố bằng cách sử dụng một công cụ như công cụ tìm lỗi .

Bạn cũng nên xem các công cụ trong Công cụ gỡ lỗi cho windows . Bạn có thể theo dõi ứng dụng và xem tất cả các trường hợp ngoại lệ cơ hội đầu tiên có trước trường hợp ngoại lệ cơ hội thứ hai của bạn.

Hy vọng nó giúp...


3

Một cách tuyệt vời để gỡ lỗi như thế này là bật tối ưu hóa cho bản dựng gỡ lỗi của bạn.


2

Có lần tôi gặp sự cố khi ứng dụng hoạt động tương tự như ứng dụng của bạn. Nó hóa ra là một sự cố tràn bộ đệm khó chịu trong sprintf. Đương nhiên, nó hoạt động khi chạy với trình gỡ lỗi được đính kèm. Những gì tôi đã làm là cài đặt một bộ lọc ngoại lệ không được xử lý ( SetUnhandledExceptionFilter ), trong đó tôi chỉ chặn vô hạn (sử dụng WaitForSingleObject trên một tay cầm không có thật với giá trị thời gian chờ là INFINITE).

Vì vậy, bạn có thể một cái gì đó dọc theo dòng:

dài __stdcall MyFilter (EXCEPTION_POINTERS *)
{
    HANDLE hEvt = :: CreateEventW (0,1,0,0);
    nếu (hEvt)
    {
        if (WAIT_FAILED == :: WaitForSingleObject (hEvt, INFINITE))
        {
            // lỗi ghi nhật ký
        }
    }

}
// đâu đó trong wmain / WinMain của bạn:
SetUnhandledExceptionFilter (MyFilter);

Sau đó, tôi đính kèm trình gỡ lỗi sau khi lỗi đã tự xuất hiện (chương trình gui ngừng phản hồi).

Sau đó, bạn có thể thực hiện kết xuất và làm việc với nó sau:

.dump / ma path_to_dump_file

Hoặc gỡ lỗi nó ngay lập tức. Cách đơn giản nhất là theo dõi nơi ngữ cảnh bộ xử lý đã được lưu bởi máy xử lý ngoại lệ thời gian chạy:

sd esp Phạm vi 1003f

Lệnh sẽ tìm kiếm không gian địa chỉ ngăn xếp cho (các) bản ghi CONTEXT với thời lượng tìm kiếm. Tôi thường sử dụng một cái gì đó như 'l? 10000' . Lưu ý, không sử dụng các số lớn bất thường vì bản ghi mà bạn đang theo dõi thường ở gần khung bộ lọc ngoại lệ không được xử lý. 1003f là sự kết hợp của các cờ (tôi tin rằng nó tương ứng với CONTEXT_FULL) được sử dụng để nắm bắt trạng thái bộ xử lý. Tìm kiếm của bạn sẽ trông giống như sau:

0: 000> sd esp l1000
1003f 0012c160 0001003f 00000000 00000000 00000000? ...............

Khi bạn nhận được kết quả, hãy sử dụng địa chỉ trong lệnh cxr:

.cxr 0012c160

Điều này sẽ đưa bạn đến BỐI CẢNH mới này, chính xác tại thời điểm gặp sự cố (bạn sẽ nhận được chính xác dấu vết ngăn xếp tại thời điểm ứng dụng của bạn gặp sự cố). Ngoài ra, sử dụng:

.exr -1

để tìm ra chính xác ngoại lệ nào đã xảy ra.

Hy vọng nó giúp.


2

Đôi khi điều này xảy ra bởi vì bạn đã gói thao tác quan trọng bên trong macro "khẳng định". Như bạn có thể biết, "khẳng định" chỉ đánh giá các biểu thức trên chế độ gỡ lỗi.


1

Về vấn đề nhận thông tin chẩn đoán của bạn, bạn đã thử sử dụng adplus.vbs thay thế cho WinDbg.exe chưa? Để đính kèm vào một quy trình đang chạy, hãy sử dụng

adplus.vbs -crash -p <process_id>

Hoặc để khởi động ứng dụng trong trường hợp sự cố xảy ra nhanh chóng:

adplus.vbs -crash -sc your_app.exe

Thông tin đầy đủ về adplus.vbs có thể được tìm thấy tại: http://support.microsoft.com/kb/286350


1

Ntdll.dll với trình gỡ lỗi đính kèm

Có một sự khác biệt nhỏ giữa việc khởi chạy một chương trình từ IDE hoặc WinDbg so với khởi chạy nó từ dòng lệnh / máy tính để bàn là khi khởi chạy với trình gỡ lỗi được đính kèm (tức là IDE hoặc WinDbg) ntdll.dll sử dụng một triển khai heap khác thực hiện một số xác thực nhỏ về cấp phát / giải phóng bộ nhớ.

Bạn có thể đọc một số thông tin liên quan trong điểm ngắt người dùng không mong muốn trong ntdll.dll . Một công cụ có thể giúp bạn xác định vấn đề là PageHeap.exe .

Phân tích sự cố

Bạn đã không viết "sự cố" mà bạn đang gặp phải là gì. Khi chương trình gặp sự cố và đề nghị bạn gửi thông tin lỗi đến Microsoft, bạn sẽ có thể nhấp vào thông tin kỹ thuật và kiểm tra ít nhất là mã ngoại lệ, và với một số nỗ lực, bạn thậm chí có thể thực hiện phân tích sau khi giết mổ (xem Heisenbug : Chương trình WinApi bị lỗi trên một số máy tính) để được hướng dẫn)


1

Vista SP1 thực sự có một trình tạo kết xuất lỗi thực sự tốt được tích hợp trong hệ thống. Rất tiếc, nó không được bật theo mặc định!

Xem bài viết này: http://msdn.microsoft.com/en-us/library/bb787181(VS.85).aspx

Lợi ích của phương pháp này là không cần cài đặt thêm phần mềm nào trên hệ thống bị ảnh hưởng. Nắm chặt nó và xé nó, con!


1

Theo kinh nghiệm của tôi, đó là hầu hết các vấn đề tham nhũng bộ nhớ.

Ví dụ :

char a[8];
memset(&a[0], 0, 16);

: /*use array a doing some thing */

rất có thể bình thường ở chế độ gỡ lỗi khi một người chạy mã.

Nhưng khi phát hành, điều đó sẽ / có thể sụp đổ.

Đối với tôi, lục lọi nơi bộ nhớ không bị ràng buộc là quá vất vả.

Sử dụng một số công cụ như Visual Leak Detector (windows) hoặc valgrind (linux) là lựa chọn khôn ngoan hơn.


1

Tôi đã thấy rất nhiều câu trả lời đúng. Tuy nhiên, không có cái nào giúp được tôi. Trong trường hợp của tôi, đã có cách sử dụng sai hướng dẫn SSE với bộ nhớ không được căn chỉnh . Hãy xem thư viện toán học của bạn (nếu bạn sử dụng) và thử tắt hỗ trợ SIMD, biên dịch lại và tái tạo sự cố.

Thí dụ:

Một dự án bao gồm mathfu và sử dụng các lớp với vector STL: std :: vector <mathfu :: vec2> . Việc sử dụng như vậy có thể gây ra sự cố tại thời điểm xây dựng mục mathfu :: vec2 vì trình phân bổ mặc định STL không đảm bảo căn chỉnh 16 byte bắt buộc. Trong trường hợp này để chứng minh ý tưởng, người ta có thể xác định #define MATHFU_COMPILE_WITHOUT_SIMD_SUPPORT 1trước mỗi bao gồm của toán học , biên dịch lại trong cấu hình Phát hành và kiểm tra lại.

Các gỡ lỗiRelWithDebInfo cấu hình làm việc tốt cho dự án của tôi, nhưng không phải là phát hành một. Lý do đằng sau hành vi này có lẽ là do trình gỡ lỗi xử lý các yêu cầu cấp phát / phân bổ và thực hiện một số việc ghi sổ bộ nhớ để kiểm tra và xác minh các quyền truy cập vào bộ nhớ.

Tôi đã gặp trường hợp này trong môi trường Visual Studio 2015 và 2017.


0

Điều gì đó tương tự đã xảy ra với tôi một lần với GCC. Hóa ra đó là một sự tối ưu hóa quá mạnh chỉ được kích hoạt khi tạo bản phát hành cuối cùng chứ không phải trong quá trình phát triển.

Vâng, nói thật đó là lỗi của tôi, không phải của gcc, vì tôi đã không nhận thấy rằng mã của tôi đang dựa trên thực tế rằng việc tối ưu hóa cụ thể đó sẽ không được thực hiện.

Tôi đã mất rất nhiều thời gian để theo dõi nó và tôi chỉ đến với nó vì tôi đã hỏi trên một nhóm tin và ai đó đã khiến tôi phải suy nghĩ về nó. Vì vậy, hãy để tôi trả ơn trong trường hợp điều này cũng xảy ra với bạn.


0

Tôi thấy bài viết này hữu ích cho tình huống của bạn. ISTR các tùy chọn trình biên dịch đã hơi lỗi thời. Xem xét các tùy chọn dự án Visual Studio của bạn để xem cách tạo tệp pdb cho bản phát hành của bạn, v.v.


0

Thật đáng ngờ rằng nó sẽ xảy ra bên ngoài trình gỡ lỗi chứ không phải bên trong; chạy trong trình gỡ lỗi thường không thay đổi hành vi ứng dụng. Tôi sẽ kiểm tra sự khác biệt về môi trường giữa bảng điều khiển và IDE. Ngoài ra, hiển nhiên, biên dịch bản phát hành mà không có tối ưu hóa và với thông tin gỡ lỗi, và xem liệu điều đó có ảnh hưởng đến hành vi hay không. Cuối cùng, hãy kiểm tra các công cụ gỡ lỗi sau khi chết mà người khác đã đề xuất ở đây, thông thường bạn có thể nhận được một số manh mối từ chúng.


0

Gỡ lỗi các bản dựng phát hành có thể là một vấn đề khó khăn do việc tối ưu hóa thay đổi thứ tự các dòng mã của bạn có vẻ được thực thi. Nó thực sự có thể trở nên khó hiểu!

Một kỹ thuật để ít nhất thu hẹp vấn đề là sử dụng MessageBox () để hiển thị các câu lệnh nhanh cho biết phần nào của chương trình mà mã của bạn phải đến ("Khởi động Foo ()", "Khởi động Foo2 ()"); bắt đầu đặt chúng ở đầu các chức năng trong khu vực mã của bạn mà bạn nghi ngờ (bạn đang làm gì vào thời điểm nó bị lỗi?). Khi bạn có thể cho biết chức năng nào, hãy thay đổi các hộp thông báo thành các khối mã hoặc thậm chí các dòng riêng lẻ trong chức năng đó cho đến khi bạn thu hẹp nó xuống một vài dòng. Sau đó, bạn có thể bắt đầu in ra giá trị của các biến để xem chúng đang ở trạng thái nào tại thời điểm gặp sự cố.


Anh ấy đã thử sử dụng các bản in, vì vậy hộp tin nhắn đã chiến thắng; không mang lại điều gì mới cho bữa tiệc.
Greg Whitfield

0

Hãy thử sử dụng _CrtCheckMemory () để xem bộ nhớ được cấp phát đang ở trạng thái nào. Nếu mọi thứ suôn sẻ, _CrtCheckMemory trả về TRUE , còn lại là FALSE .


0

Bạn có thể chạy phần mềm của mình khi đã bật Cờ toàn cầu (Xem trong Công cụ gỡ lỗi dành cho Windows). Nó rất thường xuyên sẽ giúp giải quyết vấn đề.


0

Làm cho chương trình của bạn tạo một kết xuất nhỏ khi ngoại lệ xảy ra, sau đó mở nó trong trình gỡ lỗi (ví dụ: trong WinDbg). Các chức năng chính cần xem: MiniDumpWriteDump, SetUnhandledExceptionFilter


0

Đây là một trường hợp tôi đã gặp mà ai đó có thể thấy có tính hướng dẫn. Nó chỉ bị lỗi khi phát hành trong Qt Creator - không phải trong gỡ lỗi. Tôi đang sử dụng tệp .ini (vì tôi thích các ứng dụng có thể được sao chép sang các ổ đĩa khác, so với những ứng dụng bị mất cài đặt nếu Registry bị hỏng). Điều này áp dụng cho bất kỳ ứng dụng nào lưu trữ cài đặt của chúng trong cây thư mục của ứng dụng. Nếu các bản dựng gỡ lỗi và bản phát hành nằm trong các thư mục khác nhau, bạn cũng có thể có một cài đặt khác nhau giữa chúng. Tôi đã chọn tùy chọn trong một tùy chọn chưa được kiểm tra trong tùy chọn khác. Hóa ra nó là nguồn gốc của vụ tai nạn của tôi. Điều tốt tôi đã tìm thấy nó.

Tôi ghét phải nói điều đó, nhưng tôi chỉ chẩn đoán sự cố trong MS Visual Studio Community Edition; sau khi cài đặt VS, để ứng dụng của tôi gặp sự cố trong Qt Creator và chọn mở nó trong trình gỡ lỗi của Visual Studio . Mặc dù ứng dụng Qt của tôi không có thông tin ký hiệu, nhưng hóa ra các thư viện Qt có một số. Nó đã dẫn tôi đến đường dây vi phạm; vì tôi có thể thấy phương thức nào đang được gọi. (Tuy nhiên, tôi nghĩ Qt là một khung LGPL tiện lợi, mạnh mẽ và đa nền tảng.)


-3

Tôi đã gặp lỗi này và vs bị rơi ngay cả khi cố gắng làm sạch! dự án của tôi. Vì vậy, tôi đã xóa các tệp obj theo cách thủ công khỏi thư mục Release, và sau đó nó được xây dựng tốt.


-6

Tôi đồng ý với Rolf. Vì khả năng tái tạo rất quan trọng, bạn không nên có chế độ không gỡ lỗi. Tất cả các bản dựng của bạn phải có thể gỡ lỗi. Có hai mục tiêu để gỡ lỗi nhiều hơn gấp đôi tải gỡ lỗi của bạn. Chỉ gửi phiên bản "chế độ gỡ lỗi", trừ khi nó không sử dụng được. Trong trường hợp đó, hãy làm cho nó có thể sử dụng được.


Điều này có thể hoạt động cho 10% ứng dụng nhưng chắc chắn không phải cho tất cả chúng. Bạn có muốn chơi các trò chơi được phát hành dưới dạng bản dựng DEBUG không? Cung cấp mã bảo mật bí mật đã đăng ký nhãn hiệu của bạn ở chế độ thân thiện với tháo gỡ, thậm chí có thể cùng với PDB? Tôi đoán là không.
steffenj

Steffenj: Tôi muốn các nhà phát triển trò chơi tìm ra lỗi. Lý tưởng nhất là trước khi họ giao hàng, nhưng nếu là sau đó, tôi muốn họ có thể có đủ thông tin để tái tạo và theo dõi nó. nếu đó là mã bí mật, nhãn hiệu sẽ không áp dụng. PDB? Ngân hàng dữ liệu protein? trình gỡ lỗi python?
wnoise 09/10/08

IMHO, đó là một ý tưởng tồi. Các tệp thực thi lớn hơn, chúng không được tối ưu hóa và chạy chậm hơn rất nhiều. Những trường hợp này thực sự khá hiếm; mặc dù đặc biệt khó chịu khi chúng xảy ra. Bạn không nên cung cấp liên tục sản phẩm kém chất lượng, lo lắng về việc gỡ lỗi trong trường hợp xấu nhất hiếm gặp. (Của tôi không phải là một trong số nhiều người phản đối.) Tôi đã thực hiện một số chương trình cho NASA; và chúng tôi đã nói rằng ở mức tối thiểu, mỗi dòng mã nên được kiểm tra một lần. Kiểm tra đơn vị cũng có thể hữu ích.
CodeLurker
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.