Lỗi biên dịch lỗi thực thi trong c++ là gì năm 2024

Quy trình dịch là quá trình chuyển đổi từ ngôn ngữ bậc cao (NNBC) (C/C++, Pascal, Java, C#…) sang ngôn ngữ đích (ngôn ngữ máy) để máy tính có thể hiểu và thực thi. Ngôn ngữ lập trình C là một ngôn ngữ dạng biên dịch. Chương trình được viết bằng C muốn chạy được trên máy tính phải trải qua một quá trình biên dịch để chuyển đổi từ dạng mã nguồn sang chương trình dạng mã thực thi. Quá trình được chia ra làm 4 giai đoạn chính:

  • Giai đoàn tiền xử lý (Pre-processor)
  • Giai đoạn dịch NNBC sang Asembly (Compiler)
  • Giai đoạn dịch asembly sang ngôn ngữ máy (Asember)
  • Giai đoạn liên kết (Linker)

Lỗi biên dịch lỗi thực thi trong c++ là gì năm 2024

II. HOẠT ĐỘNG

1. Giai đoạn tiền xử lý – Preprocessor Giai đoạn này sẽ thực hiện:

  • Nhận mã nguồn
  • Xóa bỏ tất cả chú thích, comments của chương trình
  • Chỉ thị tiền xử lý (bắt đầu bằng #) cũng được xử lý

Ví dụ: chỉ thị

include cho phép ghép thêm mã chương trình của một tệp tiêu để vào mã nguồn cần dịch. Các hằng số được định nghĩa bằng

define sẽ được thay thế bằng giá trị cụ thể tại mỗi nơi sử dụng trong chương trình.

2. Cộng đoạn dịch Ngôn Ngữ Bậc Cao sang Assembly

  • Phân tích cú pháp (syntax) của mã nguồn NNBC
  • Chuyển chúng sang dạng mã Assembly là một ngôn ngữ bậc thấp (hợp ngữ) gần với tập lệnh của bộ vi xử lý.

3. Công đoạn dịch Assembly

  • Dich chương trình => Sang mã máy 0 và 1
  • Một tệp mã máy (.obj) sinh ra trong hệ thống sau đó.

4. Giai đoạn Linker

  • Trong giai đoạn này mã máy của một chương trình dịch từ nhiều nguồn (file .c hoặc file thư viện .lib) được liên kết lại với nhau để tạo thành chương trình đích duy nhất
  • Mã máy của các hàm thư viện gọi trong chương trình cũng được đưa vào chương trình cuối trong giai đoạn này.
  • Chính vì vậy mà các lỗi liên quan đến việc gọi hàm hay sử dụng biến tổng thể mà không tồn tại sẽ bị phát hiện. Kể cả lỗi viết chương trình chính không có hàm main() cũng được phát hiện trong liên kết.

Kết thúc quá trình tất cả các đối tượng được liên kết lại với nhau thành một chương trình có thể thực thi được (executable hay .exe) thống nhất.

Các bạn có thể tham khảo hướng dẫn liên kết 2 source file chương trình C bằng Command line qua video dưới đây.

Nếu bạn quan tâm đến các chủ đề liên quan, hãy nhấn like ? và subcribe ? tại kênh youtube của Cộng đồng kỹ thuật TAPIT để nhận thông báo về những video với các nội dung liên quan nhé! Chúc các bạn thành công.

Như đã biết, lập trình C không cung cấp hỗ trợ trực tiếp cho việc xử lý lỗi (error handling), nhưng vì là một ngôn ngữ lập trình hệ thống (system programming language), nó cung cấp cho bạn quyền truy cập ở cấp thấp hơn dưới dạng các giá trị trả về (return value).

Hầu hết các lệnh gọi hàm C hoặc Unix trả về -1 hoặc NULL trong bất kỳ trường hợp có lỗi nào và đặt (set) mã lỗi errno. Nó được đặt làm biến toàn cục (global variable) và cho biết một lỗi đã xảy ra trong bất kỳ lệnh gọi hàm nào. Bạn có thể tìm thấy các mã lỗi (error code) khác nhau được định nghĩa (define) trong file header .

Vì vậy, một nhà lập trình C có thể kiểm tra các giá trị trả về và thực hiện những hành động thích hợp dựa trên vào giá trị trả về. Một thói quen tốt là bạn nên set errno về giá trị 0 tại thời điểm khởi tạo chương trình. Giá trị 0 cho biết rằng không có lỗi trong chương trình.

errno, perror(), và strerror()

Lỗi biên dịch lỗi thực thi trong c++ là gì năm 2024

Ngôn ngữ lập trình C cung cấp hàm perror() và strerror() có thể được sử dụng để hiển thị tin nhắn văn bản được liên kết với errno.

  • Hàm perror() hiển thị chuỗi (string) được bạn truyền vào, theo sau là dấu hai chấm (:), dấu cách (space), sau đó là biểu diễn ở dạng văn bản (text) tương ứng với giá trị errno hiện tại.
  • Hàm strerror() trả về một con trỏ đến chuỗi biểu diễn dạng ở dạng văn bản của giá trị errno hiện tại.

Chúng ta hãy thử mô phỏng một điều kiện lỗi và thử mở một file không tồn tại. Ở đây ta sử dụng cả hai hàm để hiển thị cách sử dụng, nhưng bạn có thể sử dụng một hoặc nhiều cách để in lỗi của mình. Điểm quan trọng thứ hai cần lưu ý là bạn nên sử dụng stream file stderr để xuất tất cả các lỗi.

include

include

include

extern int errno; int main () { FILE * pf; int errnum; pf = fopen ("unexist.txt", "rb"); if (pf == NULL) {

  errnum = errno;
  fprintf(stderr, "Value of errno: %d\n", errno);
  perror("Error printed by perror");
  fprintf(stderr, "Error opening file: %s\n", strerror( errnum ));
} else {
  fclose (pf);
} return 0; }

Ví dụ trên sẽ in ra 3 kiểu thông báo lỗi.

Value of errno: 2 Error printed by perror: No such file or directory Error opening file: No such file or directory

Lỗi Chia Cho Số Không (Divide by Zero Errors)

Một vấn đề thường gặp của phép chia cho một số bất kỳ, lập trình viên quên kiểm tra xem liệu số bị chia có bằng 0 hay không? Nếu là 0, nó sẽ gây ra lỗi runtime.

Đoạn code sau khắc phục vấn đề này bằng việc kiểm tra xem số bị chia có bằng 0 hay không trước khi chia.

include

include

main() { int dividend = 20; int divisor = 0; int quotient; if( divisor == 0){

  fprintf(stderr, "Division by zero! Exiting...\n");
  exit(-1);
} quotient = dividend / divisor; fprintf(stderr, "Value of quotient : %d\n", quotient ); exit(0); }

Biên dịch và thực thi đoạn code trên sẽ cho kết quả như sau.

Division by zero! Exiting...

Trạng thái Thoát của Chương Trình – hàm exit()

Một thói quen tốt khi lập trình là thoát (exit) chương trình với một giá trị EXIT_SUCCESS trong trường hợp chương trình kết thúc sau khi thực thi thành công. Ở đây, EXIT_SUCCESS là một macro được định nghĩa là 0.

Nếu bạn gặp một điều kiện lỗi (error condition) trong chương trình của bạn và cần thoát ngay, bạn nên thoát với giá trị trạng thái trả về là EXIT_FAILURE, được định nghĩa là -1. Hãy xem đoạn code ví dụ sau: