Điều gì xảy ra nếu có lỗi thời gian chạy?


17

Điều gì xảy ra nếu có lỗi thời gian chạy trong một chương trình? Sẽ thực hiện chương trình chỉ dừng lại? Có cách nào để tôi nhận được Arduino để cho tôi biết lỗi là gì không?

Câu trả lời:


21

Đầu tiên, chúng ta hãy xem một vài ví dụ về những gì có thể đi sai.

Biến cục bộ chưa được khởi tạo

void setup() {
  int status;
  pinMode(13, OUTPUT);
  digitalWrite(13, status);
} 

Như Edgar Bonet đã chỉ ra trong các bình luận, các biến cục bộ như statustrong đoạn mã trên không được trình biên dịch C ++ khởi tạo ngầm. Vì vậy, kết quả của mã ở trên là không xác định. Để tránh điều đó, hãy đảm bảo bạn luôn gán giá trị cho các biến cục bộ của mình.

Mọi thứ có một chút khác biệt với các biến toàn cục và tĩnh:

Các biến toàn cục và tĩnh được đảm bảo khởi tạo thành 0 theo tiêu chuẩn C.

Nguồn: Hướng dẫn tham khảo AVR Libc - Câu hỏi thường gặp - Tôi có nên khởi tạo tất cả các biến của mình không?

Điều đó có nghĩa là bạn không nên lo lắng về việc khởi tạo chúng thành 0 trong mã của mình. Trong thực tế, bạn thực sự nên tránh nó, vì việc khởi tạo có thể lãng phí bộ nhớ. Chỉ khởi tạo chúng thành các giá trị khác 0.

Tràn bộ nhớ

int array[10];
int v = array[100];
array[-100] = 10;

Vấn đề đầu tiên ở đây là bạn không biết cái gì sẽ được gán cho v, nhưng tệ hơn là bạn không biết bạn đã làm gì với việc gán cho vị trí -100 của array.

Chuyển đến một hướng dẫn bất hợp pháp

void doSomething( void ) { 
    for (int i = 0; i < 1000; i++); 
}

void setup () 
{
    void (*funcPtr)( void );

    funcPtr = &doSomething;
    funcPtr(); // calls doSomething();

    funcPtr = NULL;
    funcPtr(); // undefined behavior
}

Cuộc gọi đầu tiên funcPtr()thực sự sẽ là một cuộc gọi đến doSomething(). Các cuộc gọi như cuộc gọi thứ hai có thể dẫn đến hành vi không xác định.

Những điều tồi tệ khác có thể xảy ra

Chà, chẳng hạn, bạn có thể hết RAM. Còn gì nữa không Trong mọi trường hợp, tôi nghĩ rằng chương trình của bạn sẽ tiếp tục chạy, có thể không phải là cách bạn dự định.

Các loại bảo vệ

Trong các hệ thống máy tính, các vấn đề như thế này thường được xử lý ở nhiều cấp độ khác nhau:

  1. Bằng trình biên dịch
  2. Bằng thời gian chạy ngôn ngữ lập trình (như trong Java chẳng hạn).
  3. Bởi hệ điều hành hoặc bộ xử lý (nếu bộ nhớ của bạn truy cập một vị trí bên ngoài ranh giới của không gian địa chỉ dành riêng cho chương trình của bạn, HĐH hoặc bộ xử lý có thể có các cơ chế an toàn để ngăn chặn điều đó)

Arduinos chỉ có sự bảo vệ hạn chế của trình biên dịch, và có lẽ không có gì khác. Tin tốt là chúng không đa tác vụ, vì vậy chương trình duy nhất bị ảnh hưởng là của bạn. Trong mọi trường hợp, bất kỳ lỗi nào trong số đó sẽ dẫn đến hành vi thất thường.

Những câu trả lời

Các giả định là tất cả các vấn đề tôi đã nêu ở trên là các vấn đề thời gian chạy.

Điều gì xảy ra nếu có lỗi thời gian chạy trong một chương trình?

Chương trình sẽ tiếp tục và những gì xảy ra sẽ phụ thuộc vào tác dụng phụ của lỗi thời gian chạy. Một cuộc gọi đến con trỏ hàm null có thể sẽ làm cho chương trình nhảy đến một vị trí không xác định.

Sẽ thực hiện chương trình chỉ dừng lại?

Không, nó sẽ tiếp tục như thể không có gì bất thường xảy ra, có lẽ là làm những gì bạn không có ý định làm. Nó có thể thiết lập lại hoặc hành động thất thường. Nó có thể biến một số đầu vào thành đầu ra và đốt một hoặc hai cảm biến (nhưng điều đó rất khó xảy ra ).

Có một số cách tôi nhận được Arduino để cho tôi biết lỗi là gì?

Tôi không nghĩ vậy. Như tôi đã nói trước đó, các cơ chế bảo vệ không có ở đó. Không có hỗ trợ thời gian chạy từ ngôn ngữ, không có hệ điều hành, không kiểm tra phần cứng để truy cập bộ nhớ ngoài giới hạn (bộ tải khởi động không được tính là một trong hai). Bạn chỉ cần cẩn thận với chương trình của bạn và có thể thiết lập mạng lưới an toàn của riêng bạn.

Lý do thiếu bảo vệ có lẽ là do bộ điều khiển Arduino quá rẻ, bộ nhớ quá ít và không nên chạy bất cứ thứ gì quá quan trọng (vâng, dường như có một sự từ chối của AVR ở đâu đó để bạn không sử dụng MCU thường được sử dụng bởi Arduino trong các hệ thống hỗ trợ cuộc sống).


1
Tuyệt quá! Câu trả lời tốt nhất tôi đã thấy trên Arduino.SE cho đến nay!
Chàng trai với chiếc mũ

1
Cảm ơn!! Tôi nghĩ chúng ta nên cố gắng đưa ra những câu trả lời tuyệt vời nhất có thể. Nhưng điều đó làm tôi lo lắng một chút rằng chúng ta không có nhiều TRẢI NGHIỆM EE EE có thể nhìn vào các câu trả lời như của tôi và tìm thấy bất kỳ sai lầm rõ ràng nào. Trên thực tế, đó là lý do tôi đăng câu trả lời mặc dù tôi không biết nhiều về MCU AVR. Đó là để xem liệu chúng ta có ai sửa nó không. Chúng tôi chắc chắn không muốn những chiếc lều thông minh như tôi nói những thứ không phù hợp và tránh xa nó. Nhưng đó có lẽ là một cuộc thảo luận cho trang Meta.
Ricardo

5
@Ricardo - Một nhận xét tôi sẽ đưa ra là các biến không được khởi tạo không rõ ràng không nhất thiết không được khởi tạo. Các biến được định nghĩa bên ngoài các hàm thường có cái gọi là "thời lượng lưu trữ tự động", sau đó được khởi tạo mặc định thành không. Xem en.cppreference.com/w/cpp/lingu/default_initialization để biết thêm thông tin. Hành vi khởi tạo đủ phức tạp đến mức có thể nguy hiểm khi dựa vào, nhưng đưa ra tuyên bố về chăn có lẽ không phải là một ý tưởng tuyệt vời.
Sói Connor

1
Hơn nữa, SRAM được khởi tạo thành 0 khi thiết lập lại hoặc khởi động, do đó bạn có thể đưa ra một số dự đoán có hiểu biết về các biến chưa được khởi tạo, nếu bạn muốn sống nguy hiểm. Bạn không nên dựa vào hành vi này, nhưng nó rất thú vị.
Sói Connor

1
Có một ví dụ thú vị về những gì xảy ra khi bạn hết SRAM tại đây: Electronics.stackexchange.com/questions/42049/ . Về cơ bản, ngăn xếp ngăn xếp một phần của đống, hoặc ngược lại. Điều này có thể làm những điều thú vị như làm hỏng một phần của khung stack (phá vỡ hàm trả về, v.v.) hoặc ghi dữ liệu không hợp lệ vào các biến.
Sói Connor

9

Không có ngoại lệ thời gian chạy. Chỉ có hành vi không xác định.

Thực sự, không có ngoại lệ nào cả . Nếu bạn cố gắng thực hiện một thao tác không hợp lệ, kết quả sẽ không xác định.

Không có kiểm tra thời gian chạy nào cả, ngoại trừ những gì bạn thực hiện. Chương trình của bạn đang chạy trên phần cứng kim loại trần. Đó là máy tính để bàn tương đương với việc chạy trong vòng 0 mọi lúc, vì ATmega không có chuông .


6

Có một cơ chế có thể đưa MCU từ trạng thái thất thường và đó là bộ đếm thời gian theo dõi . Nếu bạn đang triển khai một số mã sẽ liên tục chạy trong một vòng lặp, mã đó sẽ không chạy bất kỳ lúc nào lâu hơn một số thời gian cố định, bạn có thể đặt thời gian này là thời gian theo dõi và bật bộ hẹn giờ.

Sau đó, bạn phải liên tục thiết lập lại bộ đếm thời gian trong vòng lặp. Nếu mã của bạn đóng băng tại một số vòng lặp điều kiện sẽ không bao giờ kết thúc, thì cơ quan giám sát sẽ đếm về 0 và cuối cùng đặt lại MCU.

Bằng cách này, bạn đang mất dữ liệu, nhưng nếu bạn chạy AVR WDT ở chế độ ngắt, bạn có thể lưu trữ một số dữ liệu trước khi đặt lại MCU.

Vì vậy, bộ đếm thời gian theo dõi có thể bảo vệ mã của bạn khỏi các vòng lặp vô tận không thường xuyên.

Tài liệu: AVR132: Sử dụng Bộ định thời Watchdog nâng cao


5

Bạn sẽ cần một trình gỡ lỗi phần cứng cho một cái gì đó như thế này. Nhưng thông thường, bạn sẽ thấy chương trình không hoạt động như bạn mong đợi và sẽ phải xem phần mã đó để xác định vấn đề.

Một cách phổ biến / nhanh chóng / dễ dàng để làm điều này là thêm các câu lệnh in để in ra các giá trị của các biến hoặc bất cứ thứ gì để bạn biết chương trình đạt đến điểm đó trong mã mà không gặp vấn đề gì. Điều này sẽ giúp bạn cách ly vấn đề hơn nữa.

Tôi tin rằng VisualMicro có một số chức năng sửa lỗi được tích hợp.


3

Tôi cho rằng CPU AVR không có bất kỳ công cụ phát hiện hoặc khôi phục lỗi nào. Nó có thể chỉ dừng lại, hoặc tiếp tục bỏ qua lỗi và hậu quả. Giống như sachleen đã nói, bạn nên thêm một số câu lệnh gỡ lỗi trong chương trình của mình để in ra dữ liệu ở giữa một thao tác, để kiểm tra xem nó có hoạt động không. Nếu bạn sử dụng một biểu tượng và đặt điểm dừng, bạn có thể dễ dàng tìm thấy một vấn đề.


-2

Arduino sẽ khởi động lại (tức là nó sẽ khởi chạy lại setup()loop()).


1
Không cần thiết. Một lỗi thời gian chạy có thể làm cho chương trình đi vào một vòng lặp mà không khởi động lại.
Nick Gammon
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.