C语言read系统调用输入超16字符时程序挂起问题求助
问题根源:野指针导致的未定义行为
你的代码里最致命的问题是这行:
char *s;
这里你只声明了一个字符指针,但没有为它分配任何实际的内存空间——这是一个典型的野指针。read系统调用会尝试把用户输入的字节写入这个指针指向的地址,但这个地址是完全不确定的(可能指向栈上的随机区域、已被占用的内存,甚至是内核空间)。
当输入较短时,运气好的话,你可能刚好写到了一块暂时没被用到的内存,程序还能勉强运行;但输入超过16字符时,你覆盖了更关键的内存区域(比如函数的返回地址、栈帧的其他变量),这就触发了未定义行为,表现为程序挂起、崩溃或者其他奇怪的现象。
修复方案:为指针分配合法内存
有两种常见的修复方式,根据你的需求选择即可:
1. 使用栈上的数组(简单直接,适合小内存场景)
把野指针替换为固定大小的栈数组,确保read有合法的内存可以写入:
#include<stdio.h> #include <unistd.h> #include <string.h> int main() { // 分配101字节的栈内存:最多存100个输入字符 + 1个终止符 char s[101]; int a = read(0, s, 100); // 先检查read是否成功(避免返回-1时访问s[-1]的越界错误) if (a == -1) { perror("Failed to read input"); return 1; } // 处理换行符:如果最后一个字符是换行,替换为终止符 if (a > 0 && s[a-1] == '\n') { s[a-1] = '\0'; } else { // 没读到换行的情况(比如输入满100字符,或用户直接按EOF),手动加终止符 s[a] = '\0'; } printf("\"%s\" \n read returned: %i; NUL at: %u\n", s, a, strlen(s)); return 0; }
2. 使用动态内存分配(适合需要灵活内存大小的场景)
如果需要更灵活的内存(比如不确定输入上限),可以用malloc分配内存,记得用完后释放:
#include<stdio.h> #include <unistd.h> #include <string.h> #include <stdlib.h> int main() { // 动态分配101字节,检查分配是否成功 char *s = malloc(101); if (!s) { perror("Failed to allocate memory"); return 1; } int a = read(0, s, 100); if (a == -1) { perror("Failed to read input"); free(s); // 出错时也要记得释放内存 return 1; } if (a > 0 && s[a-1] == '\n') { s[a-1] = '\0'; } else { s[a] = '\0'; } printf("\"%s\" \n read returned: %i; NUL at: %u\n", s, a, strlen(s)); free(s); // 释放动态分配的内存,避免泄漏 return 0; }
额外注意点
- 永远不要使用未初始化的指针进行写入操作,这是C语言中最常见的bug来源之一
- 一定要检查
read、malloc这类系统调用/库函数的返回值,避免错误扩散 - 字符串必须以
'\0'结尾,否则printf、strlen这类字符串函数会出现未定义行为
内容的提问来源于stack exchange,提问作者Suraj
相关产品推荐
相关产品推荐

