C语言栈缓冲区溢出的中途检测、修复及正常执行方法咨询
C语言栈缓冲区溢出的检测、修复与执行恢复方案
问题场景
用户代码(修正character为char笔误后):
char dform[12]; strcpy(dform, "june-11-2024"); // 该字符串含终止符共12字节,超出数组容量 checkdate(dform); // 调用子程序时触发栈缓冲区溢出
注:dform[12]的有效容量为11个字符加1个字符串终止符'\0',输入字符串长度超标导致溢出,需在子程序中检测并修复,实现类似C#异常处理的执行恢复效果。
一、栈缓冲区溢出的检测方法
C语言无内置栈溢出检测机制,需手动实现或借助编译特性:
传递数组容量并检测字符串长度
在调用子程序时同时传入数组的有效容量,子程序内通过strlen()计算实际字符串长度,与容量对比判断溢出:void checkdate(char *dform, size_t max_valid_len) { size_t actual_len = strlen(dform); if (actual_len > max_valid_len) { // 触发溢出检测逻辑 printf("检测到溢出:字符串长度%zu,超出最大允许长度%zu\n", actual_len, max_valid_len); } // 原有日期检查逻辑... }调用时传入有效容量:
checkdate(dform, sizeof(dform)/sizeof(dform[0]) - 1); // 减1预留终止符位置编译器栈保护特性(仅用于终止溢出程序)
如GCC添加-fstack-protector-all编译选项,会在栈帧插入保护字节,溢出时直接终止程序,但无法实现中途修复与执行恢复,仅适合预防场景。
二、溢出后的修复与执行恢复
要实现异常处理式的恢复执行,可通过以下方式:
子程序内截断字符串修复
检测到溢出后,手动截断字符串至有效长度并补全终止符,随后继续执行原有逻辑:void checkdate(char *dform, size_t max_valid_len) { size_t actual_len = strlen(dform); if (actual_len > max_valid_len) { // 截断字符串,保留max_valid_len个字符并添加终止符 dform[max_valid_len] = '\0'; printf("已修复溢出:截断后的字符串为%s\n", dform); } // 继续执行日期验证等原有逻辑... }返回错误码由调用方修复
子程序返回溢出错误码,调用方根据错误码修正字符串后重新调用:// 定义错误码 #define DATE_OVERFLOW 1 #define DATE_VALID 0 int checkdate(char *dform, size_t max_valid_len) { size_t actual_len = strlen(dform); if (actual_len > max_valid_len) { return DATE_OVERFLOW; } // 日期验证逻辑... return DATE_VALID; }调用方处理:
char dform[12]; strcpy(dform, "june-11-2024"); int ret = checkdate(dform, sizeof(dform)/sizeof(dform[0]) - 1); if (ret == DATE_OVERFLOW) { // 替换为符合长度要求的字符串 strncpy(dform, "jun-11-2024", sizeof(dform)-1); dform[sizeof(dform)-1] = '\0'; // 确保终止符存在 // 重新调用子程序 checkdate(dform, sizeof(dform)/sizeof(dform[0]) - 1); }
三、根源避免溢出:使用安全字符串函数
优先使用strncpy替代strcpy,从源头避免溢出:
char dform[12]; // 最多写入11个字符,手动补全终止符 strncpy(dform, "june-11-2024", sizeof(dform)-1); dform[sizeof(dform)-1] = '\0'; checkdate(dform);
内容的提问来源于stack exchange,提问作者CC_Fingers
相关产品推荐
相关产品推荐

