为何C语言中调换函数调用顺序会触发段错误?
字符指针数组操作的段错误与调用顺序问题分析
核心问题根源
你的longest_name()函数里存在未初始化野指针的致命问题:
void longest_name(char **stu){ int len = 0, mx = 0; char *name; // 未初始化,是野指针 printf("\n Address is %p \n",name); for(int i = 0; i < 10; i++){ if(mx < strlen(stu[i])){ mx = strlen(stu[i]); strcpy(name, stu[i]); // 往野指针指向的随机内存写数据,属于未定义行为 } } // ... }
char *name声明后没有初始化,指向内存中的随机地址。strcpy(name, stu[i])会把字符串写入这个随机地址,这属于C语言中的未定义行为——这种行为的结果完全不可预测:有时候可能碰巧写入了一块暂时可用的内存,程序不会立刻崩溃;有时候会写入受保护的内存区域,直接触发段错误。
为什么调用顺序会影响结果
调用不同函数会改变程序栈帧的状态:
- 当先调用
unique()再调用longest_name()时,unique()执行时的栈操作,可能让longest_name()里的野指针name刚好指向栈上一块暂时闲置、可写入的内存区域,这时strcpy的操作不会立刻触发崩溃,但这只是“碰巧”的结果,本质仍然是错误的。 - 当先调用
longest_name()时,野指针name指向栈上未初始化的无效区域,或者已经被其他数据占用的内存,strcpy写入时直接触发内存访问错误,也就是你看到的段错误。
这种差异是未定义行为的随机性表现,不是unique()修复了问题,只是改变了内存布局,让错误的表现形式不同而已。
代码中的其他问题
unique()函数逻辑错误:
你原本想筛选首字符和尾字符是'a'的名字,但当前条件stu[i][0] == 'a' && stu[i][0] == 'a'完全重复,且未判断尾字符,同时原数组里有首字母大写的名字(比如"Aakash"),正确条件应该是:len = strlen(stu[i]); if (tolower(stu[i][0]) == 'a' && tolower(stu[i][len-1]) == 'a') { // ... }现有条件永远不会触发,所以
unique()总是输出None。vowel_count()数组越界问题:char name[len];中,strlen(stu[i])返回的是字符串有效长度(不含末尾'\0'),但strcpy会把字符串连同'\0'一起复制,所以数组长度应该是len + 1,否则会出现越界写入,同样属于未定义行为:int len = strlen(stu[i]), cnt = 0; char name[len + 1]; // 加1存储字符串结束符 strcpy(name, stu[i]);
正确修复longest_name()的方法
必须为name指针分配合法的可写内存,代码示例:
void longest_name(char **stu){ int mx = 0; char *name = NULL; for(int i = 0; i < 10; i++){ int current_len = strlen(stu[i]); if(mx < current_len){ mx = current_len; // 先释放之前分配的内存(如果有) if (name != NULL) { free(name); } // 分配足够的内存(+1存储'\0') name = malloc(mx + 1); if (name == NULL) { printf("内存分配失败\n"); return; } strcpy(name, stu[i]); } } if (name != NULL) { printf("Longest name is \"%s\" with length %d\n", name, mx); free(name); // 用完释放内存,避免泄漏 } else { printf("没有有效名字\n"); } }
内容的提问来源于stack exchange,提问作者Aman Pachouri
相关产品推荐
相关产品推荐

