C语言用户输入偶现异常:长输入触发程序崩溃求助
输入长度导致C程序崩溃问题排查
终端运行示例
dennis@MBP2021 Encryption % make cc Gronsfeld_Cipher.c /Users/dennis/Documents/C/programs/DJSlibrary/cs50.c -o cipher dennis@MBP2021 Encryption % ./cipher Please enter line to be encoded: This, however, is not the time. You entered: This, however, is not the time. Length: 31 The message is: This, however, is not the time. The cipher is: EZNH, SCVKOHZ, KF UFP GXF ONWX. The decipher is: THIS, HOWEVER, IS NOT THE TIME. dennis@MBP2021 Encryption % ./cipher Please enter line to be encoded: This, however, is not the time, nor the place to have fun. You entered: This, however, is not the time, nor the place to have fun. Length: 58 zsh: trace trap ./cipher dennis@MBP2021 Encryption %
问题代码片段
char data[] = "Dummy"; int keys[] = {11, 7, 13, 10, 25, 9, 8, 3}; // Do the stuff int main(void) { // Get input from user char *string_input = NULL; size_t string_size = 250; ssize_t bytes_read; printf("\nPlease enter line to be encoded: "); string_input = (char *) malloc(string_size); bytes_read = getline(&string_input, &string_size, stdin); if(bytes_read < 2) { printf("\n\nNo input was entered. Program terminating.\n"); printf("Error Code: 1\n\n"); free(string_input); return 1; } string_input[bytes_read-1] = 0; // Clear out the new line. printf("\nYou entered: %s Length: %ld\n", string_input, bytes_read-1); strcpy(data, string_input); free(string_input); // Get sizes int DataLen = strlen(data); int ks = sizeof(keys) / sizeof(keys[0]); printf("\nThe message is: %s", data); }
问题原因
核心是缓冲区溢出:
char data[] = "Dummy";定义的是栈上固定大小数组,长度仅为6(5个字符加字符串结束符\0)。strcpy函数不会检查目标数组的容量,会持续复制直到遇到\0。短输入(31字节)已经超出data的容量,属于未定义行为——只是刚好没破坏栈上关键数据(如返回地址、栈帧指针),所以暂时没崩溃;长输入(58字节)直接覆盖栈上关键数据,触发内存错误导致程序崩溃。
解决方案
有两种安全处理方式:
方式1:直接使用动态分配的string_input
既然getline已经动态分配了足够存储输入的内存,可直接用string_input替代data,省去复制步骤:
// 移除全局的char data[] = "Dummy"; int main(void) { // ... 输入逻辑保持不变 ... // 直接使用string_input,无需strcpy int DataLen = strlen(string_input); int ks = sizeof(keys) / sizeof(keys[0]); printf("\nThe message is: %s", string_input); // 最后记得释放内存 free(string_input); }
方式2:动态分配data的内存
若必须保留data变量,根据输入长度动态分配内存:
// 将全局的char data[] = "Dummy";改为指针 char *data = NULL; int main(void) { // ... 输入逻辑保持不变 ... // 动态分配足够存储输入的内存 data = malloc(strlen(string_input) + 1); if (data == NULL) { printf("内存分配失败.\n"); free(string_input); return 1; } strcpy(data, string_input); free(string_input); // ... 后续逻辑保持不变 ... // 最后记得释放data的内存 free(data); }
内容的提问来源于stack exchange,提问作者BigD
相关产品推荐
相关产品推荐

