跳到内容
[广告]欧美亚马逊SSN账号、炮灰号开售 ×

C语言中使用gets函数需要注意什么?有哪些替代方案?


推荐帖

在 C 语言编程中,我们常常会涉及到字符串操作,如文件读写、协议交互等等,此时我们可以使用 C 库中自带的字符串操作函数,由于库已经帮我们封装好了各种字符串操作的内部实现,用起来自然也是非常方便。然而,我们日常使用的库函数有一部分实际上是不安全的!稍不注意就会导致数据异常,甚至程序崩溃。下面我们就来列举几个常见的“不安全”函数,看看你中招了吗?

C语言中使用gets函数需要注意什么?有哪些替代方案?

gets – 从标准输入中读取一行字符串

gets 的函数声明如下:

char *gets(char *str)

该函数会从标准输入读取一行,并将其存储在指定的缓冲区 str 中。读取操作在遇到换行符或文件结束符时终止,并用空字符(null)终止字符串。但该函数不会检查输入字符串的长度。一旦标准输入中的字符串长度大于 str 缓冲区的大小,此时就会导致缓冲区溢出,从而引发潜在的安全漏洞:

char buffer[10];
gets(buffer);  // 如果输入的字符串长度大于 10 就会导致缓冲区溢出

替代方案:fgets

fgets 的函数声明如下:

char *fgets(char *str, int n, FILE *stream)

该函数会从指定的流 stream 读取一行,并把它存储在 str 所指向的字符串内。当读取 (n-1) 个字符时,或者读取到换行符时,或者到达文件末尾时,它会停止。由于限定了读取的最大长度(当然此处长度必须要合理,如果缓冲区本身只有 10 个字节,你却硬是传了 15 进去,那只能说是程序 BUG 了),因此就避免了产生缓冲区溢出的问题:

char buffer[10];
fgets(buffer, sizeof(buffer), stdin);  // 无论输入是多长,此处 fgets 最多只会读 9 个有效字符

strcpy – 字符串拷贝

strcpy 函数的声明如下:

char *strcpy(char *dest, const char *src)

该函数将源字符串复制到目标缓冲区中,包括终止的空字符(null)。但其不会检查目标缓冲区的大小,因此一旦源字符串长度超过目标缓冲区大小,就会导致缓冲区溢出:

char dest[10];
char *src = “This is a long string”;
strcpy(dest, src); // 可能导致缓冲区溢出

替代方案:strncpy

strncpy 函数的声明如下:

char *strncpy(char *dest, const char *src, size_t n)

该函数把 src 所指向的字符串复制到 dest,最多复制 n 个字符。当 src 的长度小于 n 时,dest 的剩余部分将用空字节填充。因此由于限制了复制的长度,同样也就不会导致缓冲区溢出。

char dest[10];
char *src = "This is a long string";
strncpy(dest, src, sizeof(dest) - 1);  // 安全复制
dest[sizeof(dest) - 1] = '';  // 确保终

strcat – 字符串拼接

strcat 函数的声明如下:

char *strcat(char *dest, const char *src)

该函数把 src 所指向的字符串追加到 dest 所指向的字符串的结尾。很显然如果 src + dest 的字符串长度大于 dest 缓冲区的大小,就会造成缓冲区溢出:

char dest[20] = “Hello, “;
char *src = “world!”;
strcat(dest, src); // 缓冲区溢出

替代方案:strncat

strncat 函数的声明如下:

char *strncat(char *dest, const char *src, size_t n)

该函数把 src 所指向的字符串追加到 dest 所指向的字符串的结尾,直到 n 字符长度为止。由于限制了最大长度,一旦长度太大,追加的字符串就会被截断,自然也就不会出现缓冲区溢出的问题:

char dest[10] = "Hello, ";
char *src = "world!";
strncat(dest, src, sizeof(dest) - strlen(dest) - 1);  // 安全追加

sprintf – 格式化字符串输出

sprintf 函数的声明如下:

int sprintf(char *str, const char *format, …)

该函数会按指定要求格式化一个字符串并将其存储在目标缓冲区中。其不检查目标缓冲区的长度,因此当格式化出来的字符串长度大于目标缓冲区长度时,就会导致缓冲区溢出:

char buffer[10];
int value = 123;
sprintf(buffer, “The value is %d”, value); // 缓冲区溢出

替代方案:snprintf

snprintf 函数的声明如下:

int snprintf ( char * str, size_t size, const char * format, … )

该函数在 sprintf 函数的基础上增加了输出字符数的限制参数,从而避免缓冲区溢出。

char buffer[10];
int value = 123;
snprintf(buffer, sizeof(buffer), “The value is %d”, value); // 安全格式化

以上就是常用的几个 “不安全” 函数,你中招了吗?如果有类似的经历可以在评论区分享。

实际在实现对应功能时还是推荐要用这些函数的安全版本,如果出于某些原因不得不用这些函数,也一定要做好输入输出的限制,尽可能杜绝潜在的风险 。

评论链接
在其他网站上分享

创建账户或登录以发表评论

您需要成为会员才能发表评论

创建一个帐户

在我们的社区注册一个新账户。很简单!

注册新账户

登入

已有账户?在此登录

立即登录
  • 告诉你朋友

    喜欢 西塞网络科技?告诉朋友!
×
×
  • 创建新的...

重要信息

我们在您的设备上放置了 cookies,以帮助改善本网站。您可以调整您的 cookie 设置,否则我们会假定您可以继续

版权所有 © 2018-2025 西塞网络科技
粤公网安备44200002444913号