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';
有帮助吗?

解决方案

没有,这是完全错误的。 realloc的应仅用于重新分配内存的malloc分配的,你只是偶然做什么工作,最终将崩溃可怕

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

您最好使用新的和删除,甚至最好使用的std :: string,但是。

其他提示

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

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

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

  • 当您传入 NULL 时,重新分配将像 malloc 一样工作:

如果PTR是无效的指针,则realloc()对指定大小的Malloc()表现为Malloc()。

更 C++ 的方式来做到这一点:

不过,您将其标记为 C++,并且使用 C++ 的 new 运算符更加类型安全。尽管 new 运算符不允许重新分配,但它可以用于分配和重新使用现有缓冲区(新放置)。

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

甚至:

#include <string>

//...

std::string str = "test";

排名前 2 的报价来源

这不应该工作。你reallocing的东西,这不是摆在首位malloced。不,它不会当它超出范围解脱出来 - 当您使用malloc或realloc,这一切都取决于你。

更新:您的编辑并没有改变任何东西 - 你仍试图realloc的东西,这不是摆在首位malloced。此外,您也不能忽视来自realloc的返回值 - 如果realloc的有别的地方移动的记忆,你会发现,在返回。换句话说:

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

的realloc后,PTR可能会指向内存中的完全不同的地方,继续使用原来的值的PTR可以让你使用一个已经释放的内存,当你认为它是不一样大。

这是很危险!这将破坏你的堆栈。如果你是一个的realloc函数,然后返回主()的堆栈上的东西,你实际上最终覆盖栈帧并返回主比其他地方()。这是一个潜在的安全漏洞。

尝试运行以下。如果崩溃的realloc的,你真的很幸运。你可以做严重损害喜欢的东西的memcpy(MyString的)。

int dostuff();

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

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

这是你永远不应该做的。尝试释放()或realloc()堆栈变量可以导致未定义的行为包括(但不限于)损坏的堆栈(导致控制的不可预知的流量),损坏的堆服务结构损坏的用户存储器。你是幸运的,如果该计划只是一个AV崩溃。它可能在某些情况下工作,但你千万不要尝试这样做。

经验法则:只返回内存为它分配的内存管理器。在这种情况下不要试图在堆栈变量返回到运行时堆。

您程序是语法上有效C ++,但因为你通过堆叠对象的地址与堆分配器它会产生不确定的行为。典型地,这意味着,当被执行时你的程序会崩溃。

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

如果一个局部变量的地址被传递到realloc()的,它可能尝试释放其存储器和其他地方分配它。由于地址从堆和realloc()运行在堆不,这将失败。最有可能的realloc()将检测的地址不从堆和中止程序。


除此之外,示例性程序包含几个逻辑错误。


char myString = NULL;

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

此外,炭被分配NULL,这是传统上分配给无效指针的地址为零。这是因为编译预处理取代由字面NULL 0。真,则在炭,也就是,还按照惯例,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;
}

您不必免费myString,因为它是在栈上(这被“释放”,留下范围时)。

realloc是非法这里,地址必须被NULL或由先前调用返回一个地址reallocmalloccalloc

声明的每个变量是在堆栈上,即使是指针:

INT * X;

变量x是在堆栈上!它是类型pointer的并保持的地址。

X =(INT *)malloc的(的sizeof(int)的);

分配由malloc返回到变量x的地址! x的内容是存储器地址!

与你在做什么的问题是,你的东西,不是一个变量搞混。您定义的myString为一个char,因此正试图改变其地址。这是不好的。

该函数realloc()的不应该改变什么传给它。这需要一个指向在堆上一些存储器(或空指针,如果什么也没有已分配),并返回一个指针,指向一些内存在堆上。

因此,或者提供一个空指针或通过的malloc()或realloc()或释放calloc()分配的指针的东西,并存储指针返回。

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

将工作,但你会想给free()MyString的。

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

在响应于第二个代码的示例:

是,这也是非法的。 myString的未使用malloc(或释放calloc)分配的,因此它不能与realloc的重新分配,或者释放与自由。

加上realloc的并不需要一个指针的指针作为它的第一个参数。这需要一个指向分配的存储器,并返回另一个(可能不同)的指针。写这样的呼叫,而不是:

myString = realloc(myString, strlen(myString)+2);
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top