Memcpy 导致块释放两次错误
Memcpy leading to block freed twice error
我有一张地图,正在根据需要进行填充。为了将地图的内容输出到另一个变量中,我正在使用 memcpy。
如果 memcpy 行被注释,我会看到输出打印正确显示。
100 => 1234 个水果
如果我取消对 memcpy 的注释,我会看到以下错误。以前看到的印刷品也没有显示。
块释放两次
退出:ExitFailure 127
#include <iostream>
#include <map>
#include <string>
struct apple
{
int iValue;
std::string str1;
};
typedef std::map<int, apple> AppleMap;
int main()
{
AppleMap one;
apple structaa;
structaa.iValue = 1234;
structaa.str1 = "Fruits";
int value = 100;
one[value]=structaa;
AppleMap::iterator it = one.find(100);
if(it != one.end())
{
std::cout << it->first << " => " << it->second.iValue << '\t' << it->second.str1 << '\n';
}
else
{
std::cout << "Value Not Found\n";
}
apple structbb;
memcpy(&structbb, &(it->second), sizeof(apple));
return 0;
}
对我做错了什么有帮助吗?
您不能使用 memcpy
复制 "deep" 结构(例如 apple
)。你的 apple
结构很深的原因是因为它包含一个 std::string
,它在堆上有内存。当您使用 memcpy
复制 std::string
时,您正在复制指向堆的指针,但现在您有两个结构(一个 structbb
和映射中的一个指向堆上的同一内存.
正确的做法是直接复制structbb
,不要使用memcpy
,即
structbb = it->second;
这将使用默认复制方法,即使用他们定义的复制方法复制每个成员。字符串成员str1
的默认复制方式是安全的,意思是复制的字符串指向一个new堆内存位置,这样旧的字符串可以安全销毁而不影响新字符串。
您还需要将此行移到 if(it != one.end()
块的保护范围内。否则,如果你得到 "value not Found",it->second
将是假的。
在内部,std::string
存储指向堆内存的指针。
当您使用 std::copy
将 apple
复制到另一个 apple
时,复制到的结构中的 std::string
将包含指向与复制自结构中的 std::string
。
因此,当结构被销毁时,两个 std::string
都会尝试释放相同的内存。这就是您收到 "block freed twice" 错误的原因。
正如 Paul R 在评论中指出的那样,解决方案是使用赋值来正确处理 std::string
:
的复制
apple structbb = it->second;
我有一张地图,正在根据需要进行填充。为了将地图的内容输出到另一个变量中,我正在使用 memcpy。
如果 memcpy 行被注释,我会看到输出打印正确显示。 100 => 1234 个水果
如果我取消对 memcpy 的注释,我会看到以下错误。以前看到的印刷品也没有显示。
块释放两次
退出:ExitFailure 127
#include <iostream>
#include <map>
#include <string>
struct apple
{
int iValue;
std::string str1;
};
typedef std::map<int, apple> AppleMap;
int main()
{
AppleMap one;
apple structaa;
structaa.iValue = 1234;
structaa.str1 = "Fruits";
int value = 100;
one[value]=structaa;
AppleMap::iterator it = one.find(100);
if(it != one.end())
{
std::cout << it->first << " => " << it->second.iValue << '\t' << it->second.str1 << '\n';
}
else
{
std::cout << "Value Not Found\n";
}
apple structbb;
memcpy(&structbb, &(it->second), sizeof(apple));
return 0;
}
对我做错了什么有帮助吗?
您不能使用 memcpy
复制 "deep" 结构(例如 apple
)。你的 apple
结构很深的原因是因为它包含一个 std::string
,它在堆上有内存。当您使用 memcpy
复制 std::string
时,您正在复制指向堆的指针,但现在您有两个结构(一个 structbb
和映射中的一个指向堆上的同一内存.
正确的做法是直接复制structbb
,不要使用memcpy
,即
structbb = it->second;
这将使用默认复制方法,即使用他们定义的复制方法复制每个成员。字符串成员str1
的默认复制方式是安全的,意思是复制的字符串指向一个new堆内存位置,这样旧的字符串可以安全销毁而不影响新字符串。
您还需要将此行移到 if(it != one.end()
块的保护范围内。否则,如果你得到 "value not Found",it->second
将是假的。
在内部,std::string
存储指向堆内存的指针。
当您使用 std::copy
将 apple
复制到另一个 apple
时,复制到的结构中的 std::string
将包含指向与复制自结构中的 std::string
。
因此,当结构被销毁时,两个 std::string
都会尝试释放相同的内存。这就是您收到 "block freed twice" 错误的原因。
正如 Paul R 在评论中指出的那样,解决方案是使用赋值来正确处理 std::string
:
apple structbb = it->second;