#include <stdio.h>
#include <stdlib.h>
char *ptr;
int n;
int main()
{
ptr = (char *)calloc(n, sizeof(char));
// First ID
printf("Enter the length of your employ ID\n");
scanf("%d", &n);
for (int i = 0; i <= n; i++)
{
scanf("%c", &ptr[i]);
}
for (int i = 0; i <= n; i++)
{
printf("%c", ptr[i]);
}
// Second ID
printf("Enter the size of new ID\n");
scanf("%d", &n);
ptr = (char *)realloc(ptr, n * sizeof(char));
for (int i = 0; i <= n; i++)
{
scanf("%c", &ptr[i]);
}
for (int i = 0; i <= n; i++)
{
printf("%c", ptr[i]);
}
// Third ID
printf("Enter the size of new ID\n");
scanf("%d", &n);
ptr =(字符 *)重新分配(ptr,n *(字符)的大小);
for (int i =0; i <=n; i++)
{
scanf("%c", &ptr[i]);
}
for (int i = 0; i <= n; i++)
{
printf("%c", ptr[i]);
}
return 0;
}
我试图获得三个人的身份证,但程序不工作,并采取输入后,一旦它刚刚退出:(。当我使用realloc一次而不是两次时,它工作得很好,有人能解释为什么吗?it takes the input and then exits
2条答案
按热度按时间sauutmhj1#
声明:
在文件作用域声明
n
。在文件作用域声明的对象具有静态存储持续时间,并且总是被初始化。在没有显式初始化的情况下,它们被隐式初始化为零。来自C标准C11 6.7.9/10:
..."如果没有显式初始化具有静态或线程存储持续时间的对象,则:
访问超出界限的内存:
然后:
为0个对象分配内存。
calloc()函数的作用是:为一个由nmemb元素组成的数组分配内存,并返回一个指向所分配内存的指针。内存被设置为零。如果nmemb或size为0,则calloc()返回NULL,或者返回一个唯一的指针值,该指针值可以在以后成功传递给free()。
如果出错,这些函数返回NULL。NULL也可以通过成功调用大小为零的malloc()或成功调用nmemb或size等于零的calloc()返回。
但是您没有检查
calloc
的返回值。然后,这句话:
尝试访问未分配的内存,从而调用未定义的行为。
因一个错误而关闭:
您已经为
n
元素分配了空间,但条件是:尝试访问
n + 1
元素,这是内存越界,您尚未分配内存,不属于您的内存,因此是未定义的行为(但这无关紧要,因为您一开始就没有分配任何内存)。关于
realloc
:realloc()函数返回一个指向新分配的内存的指针,该指针与任何类型的变量对齐,并且可以不同于ptr,如果请求失败,则返回NULL。如果size等于0,则返回NULL或一个适合传递给free()的指针。如果realloc()失败,则原始块保持不变;它不被释放或移动。
这意味着如果它失败并返回
NULL
,那么ptr
将被初始化为NULL
,并且您将失去对原始内存的所有访问权限。一种解决方案是使用另一个指针:
malloc
和family的结果。这是多余的,可能会隐藏一个bug。这些函数返回的void *
会自动提升为正确的类型。结尾换行符:
在输入缓冲区中保留一个换行符,它会被scanf的后续调用自动读取,并且可能永远不会提示您输入。
取代:
使用带有前导空格的
" %c"
可跳过可选的空格:6jjcrrmo2#
首先,请注意您使用的是:
当
n
没有在文件作用域中显式初始化时,它会自动初始化为0。因此,基本上,您可以在以下位置覆盖大小为0的缓冲区:同时超过了分配给
i <= n
的大小,该大小应该是i < n
,这可能就是原因。其次,必须在最后使用
free
释放内存分配,并检查分配是否成功。第三,在使用字符串时,您可能希望使用
%s
来使用scanf
,除非有特定的原因。更清楚且不易出错的实施方式可以是:
希望我回答了所有问题,没有遗漏任何内容(: