为何本地IDE正常的代码在Exercism上触发Segmentation fault?
错误原因分析
- 空指针访问触发段错误:Exercism的测试用例包含了传入
NULL的场景,你的代码直接调用strlen(phrase),而strlen不允许传入空指针,会直接触发内存访问错误导致段崩溃。本地测试未覆盖该用例,因此未暴露问题。 - 数组越界写入:你声明的
temp数组大小为length,有效索引范围是0到length-1,但执行了temp[length] = '\0';的越界写入操作,属于未定义行为,不同环境下表现不同,Exercism的测试环境刚好触发了错误。 - 变长数组的潜在风险:
char temp[length];是C99标准的变长数组,栈空间有限,若测试用例传入超长字符串,可能导致栈溢出,也是段错误的潜在诱因。
代码改进方案
修复后的代码解决了上述问题,同时优化了逻辑效率:
#include "isogram.h" #include <string.h> #include <ctype.h> bool is_isogram(const char phrase[]) { // 处理空指针输入 if (phrase == NULL) { return true; // 按题目定义,空字符串视为isogram } // 用固定大小数组记录字母出现情况(仅26个小写字母) bool seen[26] = {false}; const char* ptr = phrase; while (*ptr != '\0') { char c = tolower((unsigned char)*ptr); // 仅处理字母字符 if (c >= 'a' && c <= 'z') { int index = c - 'a'; if (seen[index]) { return false; } seen[index] = true; } ptr++; } return true; } // 本地测试用main函数,Exercism测试时不会调用 int main(void) { char phrase[] = "lumberjacks"; if (is_isogram(phrase)) printf("true"); else printf("false"); return 0; }
改进点说明
- 增加空指针判断:直接处理
phrase == NULL的情况,避免调用strlen导致崩溃。 - 替换变长数组:用固定大小的
seen数组记录字母出现情况,既避免栈溢出,又将时间复杂度从O(n²)降至O(n)。 - 消除越界风险:不再手动复制字符串并添加终止符,直接遍历原字符串,彻底规避数组越界问题。
- 精准逻辑处理:只关注字母字符,自动跳过空格、连字符等非字母,完全符合isogram的定义(仅字母不重复)。
内容的提问来源于stack exchange,提问作者BenG
相关产品推荐
相关产品推荐

