使用strcat()循环拼接多字符串触发段错误,求解决方法及替代方案
解决strcat触发Segmentation Fault的问题及替代实现方法
错误原因
- 你初始化的
name = ""是只读字符串常量,存储在程序的只读数据段,strcat会尝试向该地址写入数据,直接触发内存访问权限错误,导致段错误。 - 即便目标是可写内存,若未预留足够空间容纳拼接后的内容,也会引发缓冲区溢出,导致未定义行为(包括段错误)。
修复方案(基于strcat)
方案1:提前计算总长度并分配足够内存
先统计所有要拼接的字符串总长度,一次性分配足够的可写内存,再进行拼接:
#include <cs50.h> #include <stdio.h> #include <string.h> #include <stdlib.h> int main(void) { string delimiters[] = {",", "."}; int delimiter_count = sizeof(delimiters)/sizeof(delimiters[0]); // 自动计算元素数量 // 计算所有分隔符的总长度 size_t total_len = 0; for(int i = 0; i < delimiter_count; i++) { total_len += strlen(delimiters[i]); } // 分配内存,+1用于存储字符串终止符'\0' string name = malloc(total_len + 1); if (name == NULL) { fprintf(stderr, "内存分配失败\n"); return 1; } name[0] = '\0'; // 初始化为空字符串 // 循环拼接 for(int i = 0; i < delimiter_count; i++) { strcat(name, delimiters[i]); } printf("拼接结果:%s\n", name); free(name); // 释放动态分配的内存 return 0; }
方案2:动态扩展内存(适用于未知总长度的场景)
每次拼接前重新分配内存,确保有足够空间:
#include <cs50.h> #include <stdio.h> #include <string.h> #include <stdlib.h> int main(void) { string delimiters[] = {",", "."}; int delimiter_count = sizeof(delimiters)/sizeof(delimiters[0]); // 初始分配1字节存储空字符串的终止符 string name = malloc(1); if (name == NULL) { fprintf(stderr, "内存分配失败\n"); return 1; } name[0] = '\0'; for(int i = 0; i < delimiter_count; i++) { size_t current_len = strlen(name); size_t add_len = strlen(delimiters[i]); // 重新分配内存,确保能容纳现有内容+新内容+终止符 string temp = realloc(name, current_len + add_len + 1); if (temp == NULL) { fprintf(stderr, "内存分配失败\n"); free(name); // 避免内存泄漏 return 1; } name = temp; strcat(name, delimiters[i]); } printf("拼接结果:%s\n", name); free(name); return 0; }
其他实现方法
使用snprintf更安全可控
snprintf可以精确控制写入的字符数,避免缓冲区溢出,适合字符串拼接场景:
#include <cs50.h> #include <stdio.h> #include <string.h> #include <stdlib.h> int main(void) { string delimiters[] = {",", "."}; int delimiter_count = sizeof(delimiters)/sizeof(delimiters[0]); size_t total_len = 0; for(int i = 0; i < delimiter_count; i++) { total_len += strlen(delimiters[i]); } string name = malloc(total_len + 1); if (name == NULL) { fprintf(stderr, "内存分配失败\n"); return 1; } size_t write_pos = 0; for(int i = 0; i < delimiter_count; i++) { // 从当前位置写入字符串,确保不越界 write_pos += snprintf(name + write_pos, total_len - write_pos + 1, "%s", delimiters[i]); } printf("拼接结果:%s\n", name); free(name); return 0; }
关键注意事项
- 字符串常量(如
""、",")存储在只读内存,不能作为strcat的目标参数,必须使用栈上数组或堆上动态分配的可写内存。 - 动态分配内存后,必须检查
malloc/realloc的返回值,避免空指针访问。 - 用完动态分配的内存后要调用
free,防止内存泄漏。
内容的提问来源于stack exchange,提问作者Salai Saidhanyan
相关产品推荐
相关产品推荐

