防御性编程旨在通过预防潜在错误和异常情况,提高代码的可靠性和健壮性。在单片机开发中,防御性编程尤为重要,因为嵌入式系统通常运行在资源受限的环境中,错误可能导致严重后果。以下几点为本月对单片机防御性编程的学习总结。
1. 输入验证和参数检查
-
范围检查:始终验证函数输入参数是否在预期范围内。例如,若某个参数应在 0 到 255 之间,则在函数开始处添加检查:
if (param < 0 || param > 255) { return ERROR_INVALID_PARAM; }
-
空指针检查:在使用指针之前检查是否为 NULL,防止非法访问内存:
if (ptr == NULL) { return ERROR_NULL_POINTER; }
2. 边界条件处理
- 数组访问:访问数组时确保索引在有效范围内,避免越界访问:
if (index >= ARRAY_SIZE) {
return ERROR_INDEX_OUT_OF_BOUNDS;
}
3.错误处理
- 错误码:使用统一的错误码机制,确保函数在出错时返回特定错误码:
#define SUCCESS 0
#define ERROR_INVALID_PARAM -1
#define ERROR_NULL_POINTER -2
....
#define ERROR_MAX ...
- 日志记录:在检测到错误时记录错误日志,有助于调试和诊断问题
if (error) {
log_error("An error occurred");
}
4.断言
- 运行时检查:使用断言检查关键假设和不变量,捕获意外的运行时错误:
assert(param != NULL);
assert(index < ARRAY_SIZE);
5.超时处理
- 硬件接口:与硬件通信时,设置超时以防止死锁:
while (!data_received) {
if (timeout_occurred()) {
return ERROR_TIMEOUT;
}
}