堆栈& realloc问题C ++

时间:2009-03-16 14:40:00

标签: c++ c memory memory-management

int main()
{
   char myString = NULL;
   realloc(&myString, 5);
   strncpy((char *)&myString, "test", 5);
}

似乎工作正常但是,我仍然对堆栈与堆有点混淆,这是允许的吗? myString是否需要手动释放,还是在超出范围时释放?


编辑:感谢您的回复,所以我认为这同样是非法的

//I want the code to change myString to "tests"
char myString[5] = "test";
realloc(&myString, strlen(myString)+2);
myString[4] = 's';
myString[5] = '\0';

9 个答案:

答案 0 :(得分:18)

不,这是完全错误的。 realloc只能用于重新分配malloc分配的内存,你正在做的只是偶然的,最终会崩溃的

char *myString = malloc(x);
myString = realloc(myString,y);
free(myString)

最好使用new和delete,最好还是使用std :: string。

答案 1 :(得分:8)

您发布的代码存在一些问题:

  • 是的,您需要使用malloc和realloc以及其他相关的C样式内存分配函数释放您分配的所有内容。
  • 我认为你的意思是char * myString,而不是char。传递堆栈中某些东西的地址(你的字符)是完全错误的。
  • 在realloc中使用之前,需要将myString char指针初始化为NULL。
  • 你应该将4传递给strncpy而不是5,如果你有一个更大的字符串,你将覆盖内存。
  • 您应该释放您在示例中创建的缓冲区
  • 您应该检查realloc调用的返回值。 realloc()
  

[关于realloc的返回值:]成功完成大小后   不等于0,realloc()返回一个   指针(可能移动)   分配空间。如果size为0,则为   空指针或唯一指针   可以成功传递给   返回free()。如果没有   足够的可用内存,realloc()   返回一个空指针并设置errno   至[ENOMEM]。

    传递NULL时,
  • re-alloc将像malloc一样工作:
  

如果ptr是空指针,则realloc()   行为类似于malloc()   指定大小。

更多C ++方法:

您将此标记为C ++,并且使用C ++的新运算符更安全。虽然新运算符不允许重新分配,但它可用于分配和重用现有缓冲区(放置新的)。

char *myString = new char[5];
strncpy(myString, "test", 4); 
//...
delete[] myString;

甚至:

#include <string>

//...

std::string str = "test";

Source of top 2 quotes

答案 2 :(得分:3)

这应该不起作用。你正在重新分配一开始没有被malloced的东西。不,当它超出范围时它不会被释放 - 当你使用malloc或realloc时,这完全取决于你。

更新:您的编辑不会改变任何内容 - 您仍然在尝试重新分配首先没有被malloced的内容。此外,你不能忽略realloc的返回值 - 如果realloc必须将内存移动到其他地方,你会在返回中找到它。换句话说:

char* ptr = malloc(4);
ptr = realloc(ptr, 5);

在realloc之后,ptr可能指向内存中一个完全不同的位置,继续使用ptr的原始值可能会让你使用已经释放的内存并且没有你想象的那么大。

答案 3 :(得分:2)

这是危险的!这会破坏你的筹码。如果你要在函数的堆栈上重新分配然后返回main()的东西,你实际上最终会覆盖堆栈帧并返回除main()之外的某个地方。这是一个潜在的安全漏洞。

尝试运行以下内容。如果它在realloc上崩溃,你很幸运。你可以使用memcpy(&amp; myString)之类的东西造成严重的伤害。

int dostuff();

int main()
{
        dostuff();
        return 0;
}

int dostuff()
{
        char myString = NULL;
        realloc(&myString, 5);
        strncpy((char *)&myString, "test", 5);
        return 0;
}

答案 4 :(得分:2)

这是你永远不应该做的。尝试free()或realloc()堆栈变量可能导致未定义的行为,包括(但不限于)损坏的堆栈(导致不可预测的控制流),损坏的堆服务结构,损坏的用户内存。如果程序刚刚与AV崩溃,那你很幸运。它可能在某些情况下有效,但你永远不应该尝试这样做。

经验法则:仅将内存返回给分配的内存管理器。在这种情况下,不要尝试将堆栈变量返回到运行时堆。

答案 5 :(得分:1)

您的程序在语法上是有效的C ++,但它会产生未定义的行为,因为您将堆栈对象的地址传递给堆分配器。通常这意味着您的程序在执行时会崩溃。

堆栈和堆是分配给执行程序的进程的两个不同的内存区域。当您输入一个函数来保存其参数和局部变量时,堆栈会增长,并且当您从函数返回时它会自动收缩。另一方面,堆是一个单独的地址区域,可以根据需要获取内存,并且必须在不再需要时显式释放。

如果将局部变量的地址传递给realloc(),它可能会尝试释放其内存并将其分配到其他位置。由于地址不是来自堆,并且realloc()在堆上运行,因此将失败。很可能realloc()将检测地址不是来自堆并中止程序。


除此之外,示例程序包含一些逻辑错误。


char myString = NULL;

您声明一个变量来保存char,而不是字符串。 C风格的字符串具有类型char*,即指向char的指针。

此外,char被赋予NULL,地址为零,通常分配给无效指针。这是因为预处理器用文字NULL替换0。实际上,你在char中存储了一个零字节,这也是按照惯例,是C风格字符串的终结符。


realloc(&myString, 5);

如上所述,这是非法的,因为您将堆栈对象的地址传递给堆分配器。这个问题仍然存在于您的第二个代码示例中。

此外,您放弃了返回值。 realloc()返回分配新内存的地址。它可能与以前的地址不同。它甚至可能是NULL,这是realloc()告诉你内存不足的方式。


strncpy((char *)&myString, "test", 5);

这是正确的,但演员阵容是多余的。


以下是您的程序的更正确版本:


#include <stdlib.h>
#include <string.h>

int main()
{
   /* allocate space for, say, one character + terminator */
   char* myString = (char*) malloc(2);

   /* some code using myString omitted */

   /* get more space */
   myString = (char*) realloc(myString, 5);

   /* write to the string */
   strncpy(myString, "test", 5);

   /* free the memory */
   free(myString);

   return 0;
}

在C ++中,最好完全避免使用realloc()。例如,您可以使用以下内容:


#include <string>

int main()
{
   std::string myString;

   /* some code using myString */

   myString = "test";

   return 0;
}

答案 6 :(得分:0)

你不必释放myString,因为它在堆栈上(离开范围时会被“释放”)。

realloc在此处不合法,地址必须为NULL或之前致电reallocmalloccalloc时返回的地址。< / p>

您声明的每个变量都在堆栈中,甚至是指针:

int * x;

变量x在堆栈上!它的类型为pointer,并且包含一个地址。

x =(int *)malloc(sizeof(int));

malloc返回的地址分配给变量x! x的内容是内存地址!

答案 7 :(得分:0)

你所做的事情的问题在于你正在捣乱一些不是变量的东西。您将myString定义为char,因此尝试更改其地址。那很糟糕。

函数realloc()不应该改变传递给它的任何东西。它需要一个指向堆上某些内存的指针(如果没有分配任何内容,则指向空指针)并返回指向堆上某些内存的指针。

因此,您提供空指针或指向由malloc()或realloc()或calloc()分配的内容的指针,并存储返回的指针。

这样的东西
char * myString = NULL;
myString = realloc(myString, 5);

会起作用,但你会想要free()myString。

但是,在C ++中,请使用std :: string。

答案 8 :(得分:0)

回应你的第二个代码示例:

是的,这也是非法的。 myString没有使用malloc(或calloc)分配,因此无法使用realloc重新分配,或者使用free释放。

另外,realloc不会将指针指针作为其第一个参数。它需要一个指向已分配内存的指针,并返回另一个(可能是不同的)指针。写下这样的电话:

myString = realloc(myString, strlen(myString)+2);