提问人:Affectionate Mango 提问时间:1/14/2023 最后编辑:MureinikAffectionate Mango 更新时间:1/14/2023 访问量:86
Malloc 字符数组。字符串
Malloc array of characters. String
问:
我知道由于 NULL 字符,为字符串分配内存分配需要 n+1。但是,问题是,如果您分配了 10 个字符但输入了 11 个字符的字符串怎么办?
#include <stdlib.h>
int main(){
int n;
char *str;
printf("How long is your string? ");
scanf("%d", &n);
str = malloc(n+1);
if (str == NULL) printf("Uh oh.\n");
scanf("%s", str);
printf("Your string is: %s\n", str);
}
我尝试运行该程序,但结果仍然与 n+1 相同。
答:
如果您分配了 10 个字符,但向其写入了 11 个字符,则您正在写入尚未分配的内存。这具有未定义的行为 - 它可能碰巧起作用,它可能会因分段错误而崩溃,并且它可能会执行完全不同的操作。简而言之 - 不要依赖它。char*
将 11 个字节写入 10 字节缓冲区时,最后一个字节将越界。根据多种因素,程序可能会崩溃,出现意外和奇怪的行为,或者可能运行良好(即您所看到的)。换言之,行为是未定义的。你几乎总是想避免这种情况,因为它是不安全和不可预测的。
尝试将更大的字符串写入 10 字节缓冲区,例如 20 字节或 30 字节。你会看到问题开始出现。
评论
如果超出 malloc 提供的内存区域,则会损坏 RAM 堆。如果幸运的话,你的程序会立即崩溃,或者当你释放内存时,或者当你的程序在你覆盖的区域之后使用内存块时。当你的程序崩溃时,你会注意到这个错误,并有机会修复它。
如果你运气不好,你的代码就会投入生产,一些网络犯罪分子会想出如何利用你的内存溢出来诱骗你的程序运行一些恶意代码或使用他们提供给你的一些恶意数据。如果你真的不走运,你会在克雷布斯安全或其他一些信息安全新闻媒体上得到报道。
别这样。如果你对自己避免这样做的能力没有信心,就不要使用 C。请改用具有本机字符串数据类型的语言。认真地。
如果您分配了 10 个字符但输入了 11 个字符的字符串怎么办?
scanf("%s", str);
经历未定义的行为 (UB)。任何事情都可能发生,包括“我尝试运行程序,但结果仍然与 n+1 相同”,将显示为正常。
相反,始终使用 width with 和 一旦已满就停止读取。例:scanf()
"%s"
str[]
char str[10+1];
scanf("%10s", str);
由于此处是可变的,因此请考虑改用 to 读取一行输入。n
fgets()
请注意,还会读取并保存尾随 .
最好用于用户输入并完全放弃呼叫,直到您了解为什么不好。fgets()
'\n'
fgets()
scanf()
scanf()
str = malloc(n+1);
if (str == NULL) printf("Uh oh.\n");
if (fgets(str, n+1, stdin)) {
str[strcspn(str, "\n")] = 0; // Lop off potential trailing \n
评论
strchr
\0'
strchr(str, '\n')
NULL
fgets()
'\n'
评论
NULL