C 在使用循环中使用的相同变量名调用其他内存之前,需要采取哪些步骤?

C 在使用循环中使用的相同变量名调用其他内存之前,需要采取哪些步骤?,c,while-loop,malloc,C,While Loop,Malloc,在一个循环中,我调用一定量的内存,用它来存储一些字符串 当循环发生时,我将不得不将另一个内存量malloc到相同的位置 我用过的变量。内存量取决于用户的输入。代码是这样的 下面,(我简化了它) 我试过使用“免费(信息)”和其他一些东西。请让我知道您是否知道一些可以使这项工作成功的方法。在您完成消息之后(在printf之后),您应该释放(消息)来释放它 或者,您可以reallocit而不是malloc-ing它 while (1) { printf("How many characters

在一个循环中,我调用一定量的内存,用它来存储一些字符串

当循环发生时,我将不得不将另一个内存量malloc到相同的位置 我用过的变量。内存量取决于用户的输入。代码是这样的 下面,(我简化了它)


我试过使用“免费(信息)”和其他一些东西。请让我知道您是否知道一些可以使这项工作成功的方法。

在您完成
消息之后(在
printf
之后),您应该
释放(消息)
来释放它

或者,您可以
realloc
it而不是
malloc
-ing它

while (1)
{
    printf("How many characters will you type?");
    scanf("%d\n", thisMany);
您在这里的分配不正确:您要分配一个字符数为给定字符数的字符指针。因此,它应该是:

    message = (char *)malloc(sizeof(char)*(thisMany+1));

    // Always verify *allocs. They're mischievous at best, and often evil.
    if (NULL == message) {
         fprintf(stderr, "Out of memory!\n");
         exit(-1);
    }
    // One less than the number given to malloc()
    message[thisMany] = '\0';
不过,这并没有造成任何伤害,因为sizeof(char*)比sizeof(char*)大四到八倍,所以您分配的内存超出了需要。但现在这一行代码变得很危险:

    message[thisMany+1] = '\0';
您已分配此多个+1个字符,编号从0到此多。所以这个多+1字符落在分配的内存之外;所谓的“一次关闭”缓冲区溢出。应该是:

    message = (char *)malloc(sizeof(char)*(thisMany+1));

    // Always verify *allocs. They're mischievous at best, and often evil.
    if (NULL == message) {
         fprintf(stderr, "Out of memory!\n");
         exit(-1);
    }
    // One less than the number given to malloc()
    message[thisMany] = '\0';
最后:

    /* this is the stage where I don't know what to do with 'message' 
    in order for the code to work after the loop */
您需要做的是释放分配的内存

    free(message); message = NULL;
将消息重新分配为NULL并不是绝对必要的,但我发现它非常有用;释放后,
消息仍然指向分配内存的一个区域,该区域仍然具有相同的内容。所以你可以

    free(message);
    printf("%s\n", message);
有时,也许经常,它实际上会起作用,隐藏一个潜在的灾难性错误


将message设置为NULL可以保证不会发生这种情况,并提高了任何不正确的使用都会被发现的可能性。在这方面,它使行为具有确定性,这对于捕捉bug来说更好

如前所述,另一种方法是在循环之前将message设置为NULL,然后使用
realloc
而不是
malloc
<当传递空参数时,code>realloc()
的行为与
malloc
类似:

message = NULL;
for (;;) {
     // Loop
     message = realloc(...);
     if (NULL == message) {
         ...
     }
}
// finally free message outside the loop.
// Checking that it is *not* NULL, in case the check above did not exit
// but just, say, printed an error message and exited the loop via break
if (message != NULL) {
    free(message); message = NULL;
}

message[thisMany+1]='\0'是未定义的行为,因为它写入的内容超过了所分配数组的末尾。除此之外,你必须
免费(信息)以避免内存泄漏。此外,它应该是
sizeof(char)
而不是
sizeof(char*)
(仔细想想),但正是由于这个原因,您不应该硬编码该类型
sizeof message[0]
是最安全的写入方式。您还应该通过检查
malloc
的返回值来检查内存分配是否成功。此外,它应该是
scanf(“%d”,&thisMany)“将消息设置为NULL可保证立即捕获任何不正确的使用”-否。取消引用
NULL
与取消引用任何其他无效指针是相同的未定义行为。(当然,在实践中,调试空的解引用更容易,但没有任何保证。)是的,在某些情况下,将
消息设置为空并不足以造成明显的破坏-
printf()
就是一个很好的例子:它只会打印“(空)”。事实上,我通常在更危险的情况下使用指针:-)-但是谢谢,我会纠正的。@iserni谢谢。(顺便说一句,
printf()
的行为只是库编写者的聪明、谨慎和善良;这个函数不必检查
NULL
。太糟糕了,许多程序员依赖大多数现代C库来这么做……@H2CO3,我对你在另一篇评论中说的“
realloc()感到困惑)
返回
NULL
”与
malloc()
返回
NULL
有根本的不同。除了原始缓冲区变得无法访问和泄漏外,还有其他问题吗?@iserni没有,正是原始缓冲区泄漏了。当
malloc()
失败时,情况并非如此(当然,除非您重新分配给同一个指针)边注:IMO <代码> PTR=ReloLoc(PTR)当您考虑分配失败致命错误和<代码>退出()> <代码>或<代码>中止()/代码>(我在正在处理的库中这样做,因为没有办法从这样的故障中恢复)时,习语是可以接受的,但不幸的是,很多程序员在其他情况下也会这样做。