注意:请抑制有关"C++?使用std::string!"的注释。这个问题是使用C字符串,但更多的是关于内存管理,而不是一般的字符串。
我有这个功能
char* strclone( char* src )
{
char* dst = (char*)malloc(strlen(src+1));
strcpy(dst,src);
return dst;
}
该函数应该分配一个新指针(在strclone
中(,将src中的字符串写入其中,并返回新字符串的地址。
然而,当字符串为free
d时,程序中稍后会出现:
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);