Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/145.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么返回malloc';d指针在这里的结果是;“堆损坏”;免费的?_C++_C_String_Memory Management - Fatal编程技术网

C++ 为什么返回malloc';d指针在这里的结果是;“堆损坏”;免费的?

C++ 为什么返回malloc';d指针在这里的结果是;“堆损坏”;免费的?,c++,c,string,memory-management,C++,C,String,Memory Management,注意:请禁止评论“C++?使用std::string!”。这个问题是使用C字符串,但更多的是关于内存管理,而不是一般的字符串 我有这个功能 char* strclone( char* src ) { char* dst = (char*)malloc(strlen(src+1)); strcpy(dst,src); return dst; } 函数应该分配一个新指针(在strclone中),将src中的字符串写入该指针,并返回新字符串的地址 但是,当字符串是freed时

注意:请禁止评论“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:\。。。 检测到堆损坏:在0x090CC448的正常块(#39713)之后。 CRT检测到应用程序在堆缓冲区结束后写入内存。 错误发生在我在程序中调用
free(str)
的那一行。如果我将str的赋值更改为:

str = (char*)malloc( strlen( some_string_variable ) +1);
strcpy( str, some_string_variable ) ;
//...
free( str ) ; //fine now
这样就没有bug了,程序运行得很好


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

我认为问题在于您编写了

(char*)malloc(strlen(src+1));
strlen(src + 1)
请注意,在对strlen的调用中,您已经编写了

(char*)malloc(strlen(src+1));
strlen(src + 1)
而不是

strlen(src) + 1
char* dst = (char*)malloc(strlen(src+1));
第一行表示“从一个字符开始的字符串长度超过
src
”,即字符串长度减去一(如果字符串为空,则为总垃圾)。第二个是您想要的-字符串的长度加上空终止符的长度。如果使用第一个版本,则在

strcpy(dst,src);
您将结束写入超过缓冲区末尾的内容,从而导致可怕的未定义行为。在您的例子中,当您尝试释放块时,这表现为堆损坏错误,这是有意义的,因为您确实损坏了堆

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

或者,大多数编译器附带一个名为
strdup
的非标准函数,该函数与上述函数的功能完全相同。你可能会想只考虑使用它。


希望这有帮助

我认为问题在于你写了

(char*)malloc(strlen(src+1));
strlen(src + 1)
请注意,在对strlen的调用中,您已经编写了

(char*)malloc(strlen(src+1));
strlen(src + 1)
而不是

strlen(src) + 1
char* dst = (char*)malloc(strlen(src+1));
第一行表示“从一个字符开始的字符串长度超过
src
”,即字符串长度减去一(如果字符串为空,则为总垃圾)。第二个是您想要的-字符串的长度加上空终止符的长度。如果使用第一个版本,则在

strcpy(dst,src);
您将结束写入超过缓冲区末尾的内容,从而导致可怕的未定义行为。在您的例子中,当您尝试释放块时,这表现为堆损坏错误,这是有意义的,因为您确实损坏了堆

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

或者,大多数编译器附带一个名为
strdup
的非标准函数,该函数与上述函数的功能完全相同。你可能会想只考虑使用它。

希望这有帮助

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

所以我认为以下是合理的:C++?使用
std::string
strlen(src+1)
strlen(src)+1不同。因此,在对strcpy执行操作时,您将用两个元素覆盖数组的边界

所以我认为以下是合理的:C++?使用
std::string

试试这个:

malloc(strlen(src)+1)

尝试以下操作:


malloc(strlen(src)+1)

我想你应该打字

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

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

我想你应该打字

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

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

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

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

因为在最初的实现中,将指针向前移动1,然后将其传递给strlen(),这将给出字符串的长度-1。由于最后还需要空值,因此实际上是2次关闭。

发生错误的原因是您实际写入的内存超过了分配的内存。 将malloc行更改为:

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

因为在最初的实现中,将指针向前移动1,然后将其传递给strlen(),这将给出字符串的长度-1。因为你最后还需要空值,所以实际上你的值是2。

你能给出一个完整的例子来说明这个问题吗?@Oli:一行就够了,不用麻烦了!你能给出一个完整的例子来说明这个问题吗?@Oli:一行就够了,不用麻烦了!请注意,尽管断言它“更多地是关于内存管理而不是一般的字符串”,但这实际上是一个C字符串(
strlen
)问题。这就是为什么C字符串如此危险;即使所有事实都指向另一个方向,也很容易让自己相信自己做得对。请注意,尽管断言它“更多地是关于内存管理,而不是一般的字符串”,但这实际上是一个C字符串(
strlen
)问题。这就是为什么C字符串如此危险;即使所有事实都指向另一个方向,你也很容易说服自己你做得对。