Dấu vết ngăn xếp C++23

Gỡ lỗi là một trong những bộ kỹ năng có giá trị nhất khi nói đến phát triển và bảo trì phần mềm. Đây là một kỹ năng được sử dụng ở mọi giai đoạn trong vòng đời của sản phẩm. Nhà phát triển đầu tiên tạo dự án rõ ràng sẽ gặp lỗi. Những lỗi này có thể ở bất kỳ đâu, từ lỗi logic đến lỗi cú pháp và lỗi trình biên dịch. Việc đảm bảo chất lượng được thực hiện trên phần mềm có thể gặp sự cố khi các kịch bản nâng cao hơn được kiểm tra và phần mềm tương tác với các môi trường khác. Cuối cùng, sau khi phát hành sản phẩm, nó phải được hỗ trợ. Việc gỡ lỗi không kết thúc khi khách hàng nhận được phần mềm, các lỗi thường được chuyển trở lại công ty, người sẽ lại cần gỡ lỗi

Mục tiêu của hướng dẫn này là gì?

Hướng dẫn này chỉ đơn thuần là phần giới thiệu về gỡ lỗi. Đây sẽ được coi là "hướng dẫn số 1" và tôi sẽ viết thêm tiện ích bổ sung nếu phản hồi tốt. Có rất nhiều kỹ thuật sửa lỗi phức tạp và các vấn đề khó biết bắt đầu từ đâu. Hướng dẫn này cố gắng bắt đầu từ đầu và giúp bạn làm quen với gỡ lỗi. Tôi hy vọng sẽ đưa những người mới và lập trình viên trình độ trung cấp đến với thế giới gỡ lỗi nâng cao. Gỡ lỗi "nâng cao", về cơ bản không cần biên dịch lại, không cần thực hiện "hộp thông báo hoặc gỡ lỗi

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug
2"

Trình gỡ lỗi và hệ điều hành

Để tải xuống trình gỡ lỗi mới nhất từ ​​​​Microsoft, hãy truy cập tại đây

CDB, NTSD và Windbg

Bài viết này sẽ nói chung về Windows 2000 và các Hệ điều hành cao hơn. Ba trình gỡ lỗi mà chúng ta sẽ nói ở đây là CDB, NTSD và WinDbg. Windows 2000 và các hệ thống cao hơn thường đã cài đặt NTSD trên hệ thống. Đây là một phần thưởng lớn vì bạn không cần cài đặt bất kỳ phần mềm bổ sung nào để gỡ lỗi nhanh

Vậy sự khác biệt là gì? . Điều đó đúng. NTSD không cần cửa sổ bảng điều khiển để chạy, trong khi CDB thì không. Tuy nhiên, tôi đã thấy rằng có rất nhiều sự khác biệt. Đầu tiên là các NTSD cũ hơn không hỗ trợ các tệp ký hiệu PDB, chúng chỉ hỗ trợ DBG. Tôi cũng thấy rằng NTSD không hỗ trợ máy chủ biểu tượng, trong khi CDB thì có. Các NTSD cũ hơn không thể tạo kết xuất bộ nhớ và tôi cũng đã tìm thấy các vấn đề khác như NTSD chỉ hỗ trợ tối đa 2 lệnh điểm dừng. Có một lợi thế mà NTSD hiện có mà CDB không. Khả năng không có cửa sổ giao diện điều khiển

Khả năng không có cửa sổ bảng điều khiển là rất quan trọng khi bạn đang gỡ lỗi một dịch vụ hoặc quy trình ở chế độ người dùng trước khi bất kỳ ai đăng nhập vào hệ thống. Nếu chưa có ai đăng nhập vào hệ thống, bạn không thể tạo cửa sổ giao diện điều khiển. Có một tùy chọn dòng lệnh, -d, chỉ định cho NTSD giao tiếp với trình gỡ lỗi hạt nhân đính kèm [CDB có cùng tùy chọn]. Điều này có thể được sử dụng trên các quy trình trong khi khởi động để gỡ lỗi chúng thông qua trình gỡ lỗi kernel. Mặc dù bạn đã có thể gỡ lỗi một quy trình bằng trình gỡ lỗi kernel, nhưng điều này cho phép bạn linh hoạt gỡ lỗi quy trình bằng trình gỡ lỗi chế độ người dùng. Điều này nằm ngoài phạm vi của bài viết giới thiệu hiện tại này, bây giờ chỉ cần tiêu hóa khái niệm

WinDbg và CDB về cơ bản giống nhau với một số ngoại lệ. Đầu tiên là WinDbg là GUI và CDB là ứng dụng bảng điều khiển. WinDbg cũng hỗ trợ gỡ lỗi kernel và gỡ lỗi mức nguồn

Trình gỡ lỗi Visual C++

Tôi không sử dụng trình gỡ lỗi này và tôi không khuyên bạn nên sử dụng nó. Lý do là trình gỡ lỗi này trước hết là một con heo tài nguyên. Nó tải chậm và không chỉ chứa các công cụ sửa lỗi khiến nó trở nên cồng kềnh. Lý do thứ hai là nói chung, bạn cần khởi động lại sau khi cài đặt trình gỡ lỗi này. Tôi thường giải quyết vấn đề chính rằng máy đang chạy hoặc kiểm tra phần mềm có thể chưa cài đặt trình gỡ lỗi. VC++ cũng là một cài đặt lớn, tốn thời gian

Windows 9x/TÔI

Chúng ta có thể làm gì trên Windows 9x/ME? . API gỡ lỗi giống nhau cho tất cả các hệ thống, vì vậy tôi đã biết từ lâu rằng WinDbg chỉ nên "hoạt động" trên Windows 9x/ME. Mối quan tâm duy nhất của tôi là nếu WinDbg cố gắng phát hiện nó trên Windows 9x và không cho phép gỡ lỗi. Gần đây tôi thấy điều này là không đúng sự thật. Vấn đề duy nhất là các bản cài đặt WinDbg mới nhất là các gói MSI không cài đặt trên Windows 9x. Điều này có thể được giải quyết đơn giản bằng cách cài đặt chúng trên máy dựa trên NT và chia sẻ thư mục hoặc thậm chí đưa nó vào đĩa CD. Tuy nhiên, điều này rõ ràng có các tác dụng phụ khác, chẳng hạn như bạn không nghĩ rằng mình có thể sử dụng tất cả. lệnh xxx khi NT và 9x đặt dữ liệu của họ vào các vị trí bộ nhớ khác nhau. Các biểu tượng có hoạt động không? . Mặc dù vậy, tôi đã thấy bước qua mã sau khi đặt ba r1 xxxxx rất chậm. Bài viết này không bao gồm Windows 9x/ME

Thiết lập môi trường của bạn

Đây là một bước rất quan trọng trước khi bạn bắt đầu gỡ lỗi hoặc thiết lập thành công môi trường gỡ lỗi của mình. Hệ thống cần được cấu hình theo ý thích của bạn và chứa tất cả các công cụ bạn cần

Biểu tượng và Máy chủ biểu tượng

Biểu tượng là một phần quan trọng của bất kỳ thao tác gỡ lỗi nào. Microsoft chứa một vị trí nơi bạn có thể tải xuống tất cả các biểu tượng cho bất kỳ Hệ điều hành cụ thể nào [Windows XP, v.v. ]. Vấn đề là, bạn cần có nhiều dung lượng đĩa cứng và nếu bạn gỡ lỗi nhiều Hệ điều hành trên một máy [từ các bãi chứa sự cố, v.v. ], thì điều này thật rườm rà

Để đáp ứng nhu cầu gỡ lỗi nhiều Hệ điều hành này, Microsoft hỗ trợ một "máy chủ biểu tượng". Điều này sẽ giúp bạn có được các biểu tượng chính xác trên hệ thống của mình. Máy chủ biểu tượng được đặt tại đây. Nếu bạn đặt đường dẫn biểu tượng của mình đến vị trí này, trình gỡ lỗi của bạn sẽ tự động tải xuống các biểu tượng hệ thống mà bạn cần. Các biểu tượng mà bạn cần cho ứng dụng của mình tùy thuộc vào bạn

Tùy chọn thực thi tệp hình ảnh

Có một vị trí trong sổ đăng ký sẽ tự động đính kèm trình gỡ lỗi vào ứng dụng khi ứng dụng bắt đầu chạy. Vị trí đăng ký này là như sau

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows 
     NT\CurrentVersion\Image File Execution Options

Trong khóa đăng ký này, bạn chỉ cần tạo một khóa đăng ký mới với tên của quy trình bạn muốn gỡ lỗi, chẳng hạn như "myapplication. exe". Nếu bạn chưa từng sử dụng mã này trước đây, thì có thể có một khóa mặc định đã được tạo có tên là "Ứng dụng của bạn ở đây" hoặc một cái gì đó tương tự. Bạn có thể đổi tên khóa đó và sử dụng nó nếu muốn

Một trong những giá trị trên khóa này là "Trình gỡ lỗi". Điều này sẽ trỏ đến trình gỡ lỗi mà bạn muốn bắt đầu khi ứng dụng này chạy. Mặc định cho "Ứng dụng của bạn ở đây" là "ntsd -d". Bạn không thể sử dụng cái này trừ khi bạn có trình gỡ lỗi hạt nhân được đính kèm, vì vậy tôi sẽ xóa phần "-d"

Ghi chú. Giữ "-d" và không đính kèm trình gỡ lỗi hạt nhân có thể dẫn đến việc khóa hệ thống của bạn mỗi khi ứng dụng đó được chạy. Hãy cẩn thận. Nếu bạn đã thiết lập trình gỡ lỗi kernel, bạn có thể mở khóa hệ thống bằng cách nhấn "g"

Có một giá trị khác có thể được gọi là "GlobalFlags". Đây là một công cụ khác có thể được sử dụng để gỡ lỗi, tuy nhiên nó nằm ngoài phạm vi của bài viết này. Để biết thêm thông tin về điều đó, hãy tra cứu "gflags. exe"

Thiết bị gỡ lỗi hạt nhân

Để gỡ lỗi kernel, trước tiên bạn cần khởi động Hệ điều hành ở chế độ gỡ lỗi. Mặc dù có một GUI dưới thuộc tính hệ thống để làm điều này, nhưng tôi thường chỉnh sửa boot. ini trực tiếp. Xác định vị trí khởi động. ini trên thư mục gốc của C của bạn. \ lái xe. Nó rất có thể là một tập tin hệ thống ẩn. Tôi sẽ gán -r -s -h boot. ini rồi mở lên để chỉnh sửa

thận trọng. Chỉnh sửa tệp này không chính xác có thể khiến bạn không thể khởi động lại

Tệp khởi động có thể trông như thế này

[boot loader]
timeout=30
default=multi[0]disk[0]rdisk[0]partition[1]\WINDOWS
[operating systems]
multi[0]disk[0]rdisk[0]partition[1]\WINDOWS.0=
    "Microsoft Windows XP Professional" /fastdetect

Tôi sẽ sao chép dòng đầu tiên trong "Hệ điều hành"

[boot loader]
timeout=30
default=multi[0]disk[0]rdisk[0]partition[1]\WINDOWS
[operating systems]
multi[0]disk[0]rdisk[0]partition[1]\WINDOWS.0=
    "Microsoft Windows XP Professional" /fastdetect
multi[0]disk[0]rdisk[0]partition[1]\WINDOWS.0=
   "Microsoft Windows XP Professional" 
   /fastdetect /debug /debugport=COM1 /baudrate=115200

Sau đó, dòng trùng lặp có thể chứa thiết lập của bạn. /debug, sau đó là /debugport=port và cuối cùng là /baudrate=baudrate. Cổng gỡ lỗi để sử dụng là cổng của máy mà bạn sẽ kết nối CÁP MODEM NULL NỐI TIẾP của mình. Đây là một phần cứng mà bạn cần. Bạn cũng sẽ cần một máy khác. Ngoài việc sử dụng các cổng COM, bạn có thể sử dụng firewire nhanh hơn rất nhiều

Lần tới khi bạn khởi động, chỉ cần chọn lựa chọn "Đã bật trình gỡ lỗi" để khởi động ở chế độ gỡ lỗi

Biến môi trường

Tôi thường thiết lập

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug
3 để trỏ đến máy chủ Biểu tượng của Microsoft và thư mục cục bộ chứa thông tin biểu tượng của bạn. Để đặt đường dẫn môi trường này, hãy chuyển đến Thuộc tính hệ thống -> Nâng cao -> Biến môi trường

Trình gỡ lỗi mặc định

Đây là trình sửa lỗi mặc định sẽ được sử dụng khi có bất kỳ sự cố nào xảy ra trên hệ thống. Theo mặc định, nó thường được đặt thành "Bác sĩ Watson". Chương trình đó không đáng nói ở đây. Khóa đăng ký là vị trí này

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug

Tôi sẽ đặt "Tự động" thành 1 và "Trình gỡ lỗi" thành trình gỡ lỗi của bạn

Hội đồng

Tôi thực sự khuyên bạn nên học lập trình hợp ngữ. Các hướng dẫn này sẽ không hiển thị gỡ lỗi cấp nguồn vì tôi chưa bao giờ làm điều đó và tôi thậm chí không biết làm thế nào. Các vấn đề với gỡ lỗi cấp nguồn là nguồn không phải lúc nào cũng có sẵn cũng như đôi khi vấn đề không được nhìn thấy khi chỉ nhìn vào nguồn mà thay vào đó là mã được tạo. Nó cũng làm cho hệ thống đi bộ dễ dàng hơn nhiều. Nếu bạn hiểu cách thiết lập môi trường, bạn có thể dễ dàng đảo ngược hệ thống để tìm ra thông tin bạn cần biết và có thể không phải lúc nào thông tin này cũng có sẵn bằng cách sử dụng tính năng gỡ lỗi Cấp nguồn

Một điều khác tôi ghét về gỡ lỗi cấp nguồn là nếu nguồn không khớp với các ký hiệu, trình gỡ lỗi nguồn sẽ không hiển thị cho bạn thông tin chính xác. Điều này có nghĩa là nếu bạn tạo nhiều bản dựng chương trình của mình hoặc thay đổi chương trình của mình sau khi bạn đã tạo, thì bạn nên tìm nguồn phù hợp với bản dựng mà bạn đang gỡ lỗi.

Bắt đầu nào

Hướng dẫn này về cơ bản là Phần Một và nếu nó thích, tôi sẽ viết thêm, mỗi ngày càng nâng cao. Hướng dẫn đầu tiên này sẽ hướng dẫn một vài kịch bản đơn giản về các vấn đề lập trình ở chế độ người dùng

Biểu tượng cho các tệp thực thi phát hành

Đầu tiên, làm thế nào để bạn tạo các ký hiệu cho các nhị phân "phát hành"? . Bạn tạo một tệp tạo để khởi động lại các tệp nhị phân một cách chính xác

Các tùy chọn tôi thường sử dụng cho cl. exe sẽ là

/nologo /MD /W3 /Oxs /Zi /I "..\..\inc" /D "WIN32" /D "_WINDOWS" 
/Fr$[OBJDIR]\\ /Fo$[OBJDIR]\\ /Fd$[OBJDIR]\\ /c

Các tùy chọn tôi thường sử dụng cho liên kết. exe sẽ là

/nologo /subsystem:console 
  /out:$[TARGETDIR]\$[TARGET]/pdb:.pdb 
  /debug /debugtype:both 
/LIBPATH:"..\..\..\bin\lib"

Điều này sẽ tạo ra các. PDB cho dự án của bạn. Tất nhiên, với sự ra đời của VC++ 7, họ đã loại bỏ. DBG [vì vậy /debugtype. cả hai có thể lỗi trên trình biên dịch này]. . DBG là một phiên bản nhỏ hơn của. PDB và nó không chứa thông tin nguồn, tra cứu ký hiệu nghiêm ngặt. Nó thậm chí không chứa các tham số hoặc bất cứ thứ gì. Nếu bạn đang sử dụng trình biên dịch vẫn có thể tạo chúng, đây là những gì bạn làm

________số 8

-b là vị trí bộ nhớ mới để khởi động lại tệp thực thi thành. Tuy nhiên, điều này sẽ loại bỏ các biểu tượng gỡ lỗi khỏi bản phát hành thực thi làm cho nó có kích thước nhỏ hơn. Nếu bạn xây dựng một tệp thực thi theo phương thức Visual Studio mặc định, nó có thể nhỏ hơn một chút so với tệp thực thi này. Tuy nhiên, bạn không có biểu tượng. Mã được tạo giống nhau và được tối ưu hóa bằng cờ tối ưu hóa mà bạn chỉ định. Sự khác biệt là những mã nhị phân này hiện hữu ích hơn, vì bất kể chúng đi đâu hay ai sử dụng chúng ở đâu, bạn vẫn có thể nhận được các ký hiệu

Hãy nhớ rằng, việc gỡ lỗi tốt nhất luôn xảy ra nếu bạn không phải xây dựng lại tệp thực thi. Khi bạn phải xây dựng lại tệp thực thi, bạn cũng phải biết rằng bạn hiện đã thay đổi bản in bộ nhớ của tệp thực thi. Bạn cũng có thể đã thay đổi tốc độ của tệp thực thi. Điều này rất quan trọng vì bây giờ bạn phải tạo lại sự cố bằng mã nhị phân này. Điều gì xảy ra nếu phải mất 4 ngày để gây ra sự cố này?

Bẫy vi phạm truy cập đơn giản

Hãy đi qua một vấn đề đơn giản. Chương trình của bạn gặp sự cố với "Vi phạm quyền truy cập", đây không phải là hiếm. Đây có lẽ là vấn đề thường xuyên xảy ra nhất khi chạy một tệp thực thi. Có ba bước để giúp giải quyết vấn đề này

  1. Ai đang cố gắng truy cập?
  2. Nó đang cố truy cập vào cái gì?
  3. Tại sao nó cố gắng truy cập nó?

Đây là những hướng dẫn chung để giải quyết vấn đề này. Tôi đặt #2 in nghiêng vì nó có lẽ là quan trọng nhất trong ba. Tuy nhiên, giải 1 và 3 cũng có thể giúp xác định #2 nếu nó không rõ ràng ngay lập tức

Tôi đã tạo một chương trình rất đơn giản bị treo. Tôi đã thiết lập trình gỡ lỗi mặc định của mình thành CDB và bây giờ tôi chỉ cần chạy chương trình. Tôi cũng đã tạo các biểu tượng cho tệp thực thi này cũng như đặt

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug
3 thành máy chủ biểu tượng của Microsoft

Như chúng ta có thể thấy, đây là những gì xảy ra khi chúng ta chạy chương trình

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows 
     NT\CurrentVersion\Image File Execution Options
0

What is the first thing we notice? This trap occurred in MSVCRT.DLL. This is apparent because the debugger generally displays this information using !+offset. This means the closest symbol in MSVCRT.DLL is

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug
5 and we are +18h bytes into it. Given that this is such a small offset and providing that the symbols are correct [even symbols can be incorrect, but that's a later tutorial], we can assume that we are in
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug
6 function of MSVCRT.

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows 
     NT\CurrentVersion\Image File Execution Options
3

Nếu chúng ta muốn chứng minh điều này, chúng ta có thể làm gì?

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows 
     NT\CurrentVersion\Image File Execution Options
4

Lệnh này sẽ cung cấp cho chúng ta danh sách tất cả các mô-đun trong quy trình với vị trí bộ nhớ bắt đầu và kết thúc của chúng. Cái bẫy của chúng ta ở 77c3f10b, tức là 77c10000

Chủ Đề