为什么在这里返回一个 malloc'd 指针会导致免费"HEAP CORRUPTION"?



注意:请抑制有关"C++?使用std::string!"的注释。这个问题是使用C字符串,但更多的是关于内存管理,而不是一般的字符串。

我有这个功能

char* strclone( char* src )
{
    char* dst = (char*)malloc(strlen(src+1));
    strcpy(dst,src);
    return dst;
}

该函数应该分配一个新指针(在strclone中(,将src中的字符串写入其中,并返回新字符串的地址。

然而,当字符串为freed时,程序中稍后会出现:

str = strclone( some_str_variable );    
// ..code..
free( str ) ; //! ERROR!  

错误显示:

调试错误!程序:C:\。。。检测到HEAP腐蚀:在0x090CC448的正常块(#39713(之后。CRT检测到应用程序在堆缓冲区结束后写入内存。

错误发生在我在程序中调用free( str )的那一行。如果我将str的分配更改为:

str = (char*)malloc( strlen( some_string_variable ) +1);
strcpy( str, some_string_variable ) ;
//...
free( str ) ; //fine now

然后就没有错误了,程序运行得很完美。

为什么strclone功能不能按预期工作?

我认为问题在于您编写了

(char*)malloc(strlen(src+1));

请注意,在对strlen的调用中,您已经编写了

strlen(src + 1)

而不是

strlen(src) + 1

第一行表示"从src后一个字符开始的字符串的长度",即字符串的长度减去1(如果字符串为空,则为总垃圾(。第二个是你想要的——字符串的长度加上null终止符的一。如果你使用第一个版本,那么在行

strcpy(dst,src);

您最终会在缓冲区结束后进行写入,从而导致可怕的"未定义行为"。在您的情况下,当您尝试释放块时,这表现为堆损坏错误,这是有道理的,因为您确实损坏了堆!

试着将+1从括号中移出,看看它是否能解决问题。

或者,大多数编译器都附带了一个名为strdup的非标准函数,它正是上面函数想要做的事情。您可能需要考虑只使用它。

希望这能有所帮助!

strlen(src+1)strlen(src)+1不同。因此,当对strcpy执行此操作时,您将用两个元素覆盖数组的边界。

因此,我认为以下内容是合理的:C++?使用std::string

我认为你应该键入

char* dst = (char*)malloc(strlen(src) + 1);

而不是

char* dst = (char*)malloc(strlen(src+1));

发生此错误是因为您实际上正在写入已分配的内存。将您的malloc行更改为:

char* dst = (char*)malloc(strlen(src)+1);

因为在最初的实现中,您将指针提前1,然后将其传递给strlen((,这将为您提供字符串-1的长度。由于您还需要末尾的NULL,因此实际上您已经偏离了-2。

试试这个:

malloc(strlen(src)+1);

最新更新