C语言字符串拼接程序调试:safeReadString输入无返回问题排查
C语言字符串读取拼接程序调试方案
核心问题定位
程序无法正常返回/崩溃的根源主要分为两部分:safeReadString函数存在多处逻辑硬错误,main函数存在内存操作隐患与输入输出逻辑疏漏。
一、safeReadString 函数的错误(直接导致程序崩溃的核心原因)
原函数实现存在4处致命逻辑错误:
- 循环终止条件完全错误
原循环逻辑:while((c!='\0') || (count<size))getchar()读取的输入字符不会出现'\0',用户输入回车产生的是'\n'(ASCII 10)- 逻辑或
||的判定规则是只要任意条件成立就持续循环,会导致循环永久运行、超出内存边界
正确逻辑应为:只要未遇到输入终止符(换行/EOF),且仍有剩余存储空间时才继续读取,使用逻辑与
&&做判定,同时预留1个字符的位置存储字符串结尾'\0' - 字符存储逻辑完全错误
原代码的存储逻辑:
该代码是将指针s+=c; s++;s的地址直接加上字符的ASCII值(比如输入字符a对应ASCII 97,就会把指针向后跳转97个字节),完全没有把字符存入目标内存,属于直接的野指针访问。正确存储逻辑:直接将字符赋值到当前指针指向的地址,再移动指针,即
*s = c; s++;或简写为*s++ = c; - 未处理输入残留的换行符
用户输入结束按下的回车符会被存入输入缓冲区,若不主动排除或作为循环终止标记,会被错误写入字符串内容。 - 未预留字符串结尾的存储空间
原循环最多读取size个字符,后续还要执行*s='\0'写入结尾标记,会直接超出申请的内存边界。
二、main.c 中的隐藏错误
即使修正了safeReadString的逻辑,以下问题仍会导致程序异常:
- 输出缓冲区未刷新
原代码printf("Got here");末尾未加换行符,由于stdout默认是行缓冲模式,没有换行触发缓冲区刷新时,输出会滞留在内存中,程序后续崩溃时缓冲区会被直接丢弃,无法正常打印。 insStr为野指针
原代码仅定义了char * insStr;未给指针分配任何有效内存,直接传入函数做写入操作会直接触发段错误。- 字符串拼接的索引逻辑错误
原拼接代码:
第一个循环结束后,for(i=0;i<=strlen(mainStr);i++) newStr[i]=mainStr[i]; for(int j=0;j<=strlen(insStr);j++) newStr[i+j]=insStr[j];i的值已经等于strlen(mainStr)+1(循环条件为i<=strlen(mainStr)),第二个循环使用i+j作为偏移量会直接覆盖mainStr的结尾'\0',导致拼接后的字符串无法识别边界,出现越界访问。 - 打印格式符语法错误
原代码中with:\%s\n多了冗余的反斜杠,会将格式符转义为普通文本,无法正常打印第二个字符串内容。 - 头文件缺少重复包含保护
safeStr.h未添加头文件守卫,多文件编译时可能出现符号重复定义的问题。
修正后的完整代码
safeStr.h
#ifndef SAFE_STR_H #define SAFE_STR_H #include <stdio.h> #define MAXSTR 80 void safeReadString(char *str, int size); #endif
safeStr.c
#include "safeStr.h" void safeReadString(char *str, int size) { char c; char *s = str; int count = 0; printf("Please type a string of at most %d characters.\n", size); // 正确循环判定:遇到换行/EOF、或读满size-1个字符时终止 while ((c = getchar()) != '\n' && c != EOF && count < size - 1) { *s++ = c; // 正确存储字符并移动指针 count++; } *s = '\0'; // 手动写入字符串结尾标记 // 清空输入缓冲区残留字符,避免影响下一次读取 while (c != '\n' && c != EOF) { c = getchar(); } }
main.c
#include <stdio.h> #include <string.h> #include <stdlib.h> #include "safeStr.h" int main(void){ char mainStr[MAXSTR] = "Initial string"; safeReadString(mainStr, MAXSTR); int remChars = MAXSTR - strlen(mainStr) - 1; printf("Got here\n"); if (remChars > 0) { // 给insStr分配有效堆内存 char *insStr = (char*)malloc(remChars); if (insStr == NULL) { printf("Memory allocation failed\n"); return 1; } safeReadString(insStr, remChars); int mainLen = strlen(mainStr); int insLen = strlen(insStr); // 给拼接结果分配有效内存 char *newStr = (char*)malloc(mainLen + insLen + 1); if (newStr == NULL) { printf("Memory allocation failed\n"); free(insStr); return 1; } // 直接用标准库函数完成拼接,避免手写索引错误 strcpy(newStr, mainStr); strcat(newStr, insStr); printf("The result of concatenating:\n%s\nwith: %s\nis:\n%s\n", mainStr, insStr, newStr); // 释放堆内存,避免泄漏 free(newStr); free(insStr); } else { printf("No room for inserting a string\n"); } return 0; }
内容的提问来源于stack exchange,提问作者Vel
相关产品推荐
相关产品推荐

