注意:请取消关于“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 CORRUPTION DETECTED:在正常块(#39713)之后的0x090CC448处。 CRT检测到应用程序在堆缓冲区结束后写入内存。
错误发生在我在程序中调用free( str )
的行。如果我将str的赋值更改为:
str = (char*)malloc( strlen( some_string_variable ) +1);
strcpy( str, some_string_variable ) ;
//...
free( str ) ; //fine now
然后没有错误,程序运行完美。
为什么strclone
功能无法按预期工作?
答案 0 :(得分:15)
我认为问题在于你已经写过了
(char*)malloc(strlen(src+1));
请注意,在致电strlen
时,您已写过
strlen(src + 1)
而不是
strlen(src) + 1
第一行表示“字符串的长度超过src
”,这是字符串的长度减去1(如果字符串为空则为总垃圾)。第二个是你想要的那个 - 字符串的长度加上一个空终止符。如果您使用的是第一个版本,那么就行
strcpy(dst,src);
您将最终写入缓冲区的末尾,导致可怕的未定义行为。在您的情况下,当您尝试释放块时,这表现为堆损坏错误,这是有道理的,因为您确实已经损坏了堆!
尝试从括号中移出+1,看看它是否修复了问题。
或者,大多数编译器都附带一个名为strdup
的非标准函数,它完全按照上面的函数执行的操作。您可能想要考虑使用它。
希望这有帮助!
答案 1 :(得分:3)
strlen(src+1)
与strlen(src)+1
不同。所以当你对strcpy
进行覆盖时,你会用两个元素覆盖数组的边界。
所以我认为以下是合理的: C ++?使用std::string
!
答案 2 :(得分:0)
试试这个:
malloc(strlen(src)+1);
答案 3 :(得分:0)
我相信你应该输入
char* dst = (char*)malloc(strlen(src) + 1);
而不是
char* dst = (char*)malloc(strlen(src+1));
答案 4 :(得分:0)
发生错误是因为您实际上正在写入已分配的内存。 将malloc行更改为:
char* dst = (char*)malloc(strlen(src)+1);
因为在您的原始实现中,您将指针前进1,然后将其传递给strlen(),这将为您提供字符串-1的长度。由于你最后还需要NULL,所以你实际上是2分。