C语言双指针传递字符串修改后无法同步至原变量的问题
C语言
removeNonAlphaCharacters函数问题排查与修复 我需要实现一个removeNonAlphaCharacters函数来移除非字母字符,但遇到两个核心问题:
- 无法将修改后的字符串传递回主函数,最终
printf输出不符合预期 - 直接覆盖原字符串会触发
SIGBUS内存错误
原代码如下:
#include <stdio.h> #include <string.h> #include <stdlib.h> int removeNonAlphaCharacters(char ** source); int main() { char * source = "Hello 2 Data!"; char **sourcePointer = &source; int result = 0; result = removeNonAlphaCharacters(sourcePointer); printf("we have successfully removed %i characters from the string.\n", result); printf("The modified result is: %s", source); return 0; } int removeNonAlphaCharacters(char ** source) { char *dest = *source; size_t sourceLength = strnlen(*source, 100); char *str = malloc(sourceLength*sizeof(char)); int removeNum = 0; for (; *dest != '\0'; dest++) { if (*dest >= 'A' && *dest <= 'Z' || *dest >= 'a' && *dest <= 'z') { *str = *dest; str++; } else { removeNum++; continue; } } printf("The modified result is: %s\n", str-(sourceLength-removeNum)); *source = malloc((sourceLength-removeNum) * sizeof(char)); strncpy(*source, str, 100); return removeNum; }
核心错误点
- 字符串字面量不可修改:main函数中
char *source = "Hello 2 Data!";定义的是字符串字面量,存储在只读内存段,直接尝试修改会触发内存访问错误(SIGBUS)。 - 指针偏移导致拷贝失效:函数内
str指针在循环中不断后移,最终指向临时缓冲区的末尾位置,此时用strncpy(*source, str, 100)拷贝的是空白/垃圾数据,而非有效字符的起始地址。 - 缺少字符串终止符:新分配的内存没有添加
'\0',printf无法识别字符串结束位置,会输出乱码。 - 内存泄漏:第一次
malloc的str缓冲区没有释放,造成内存浪费。
修复后的代码
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> // 使用isalpha简化字母判断 int removeNonAlphaCharacters(char **source); int main() { // 将字符串字面量复制到堆内存(可写区域) char *source = strdup("Hello 2 Data!"); if (source == NULL) { perror("strdup failed"); return 1; } char **sourcePointer = &source; int result = 0; result = removeNonAlphaCharacters(sourcePointer); printf("we have successfully removed %i characters from the string.\n", result); printf("The modified result is: %s\n", source); free(source); // 释放动态分配的内存,避免泄漏 return 0; } int removeNonAlphaCharacters(char **source) { char *dest = *source; size_t sourceLength = strlen(*source); // 多分配1字节用于存储字符串终止符 char *tempBuf = malloc(sourceLength + 1); if (tempBuf == NULL) { perror("malloc failed"); return -1; } // 保存缓冲区起始地址,避免指针偏移后丢失 char *str = tempBuf; int removeNum = 0; for (; *dest != '\0'; dest++) { // 使用isalpha判断字母,兼容locale且代码更简洁 if (isalpha((unsigned char)*dest)) { *str = *dest; str++; } else { removeNum++; } } *str = '\0'; // 必须添加字符串终止符 printf("The modified result is: %s\n", tempBuf); // 释放原字符串的动态内存,替换为新的结果缓冲区 free(*source); *source = tempBuf; return removeNum; }
关键修复说明
- 使用可写内存存储原字符串:用
strdup将字符串字面量复制到堆内存,避免修改只读区域的错误;也可以直接定义char source[] = "Hello 2 Data!";在栈上分配可写数组。 - 保存临时缓冲区起始地址:用
tempBuf记录malloc的起始位置,避免str指针偏移后找不到有效数据的起始点。 - 添加字符串终止符:在临时缓冲区末尾添加
'\0',确保printf能正确识别字符串结束。 - 避免内存泄漏:释放原字符串的动态内存,同时将临时缓冲区直接赋值给
*source,去掉原代码中多余的二次malloc操作。 - 用
isalpha简化判断:替代手动的ASCII范围判断,代码更简洁且支持locale相关的字母判断。
内容的提问来源于stack exchange,提问作者rui wang
相关产品推荐
相关产品推荐

