C++ 自定义 std::map<>导致内存冲突的键类
C++ Custom std::map<> key class causing memory violation
我第一次写了一个类,它应该是可用的std::map<>
的键类型。我已经重载了复制构造函数、赋值和operator <
,就像其他关于SO的问题中建议的那样。但由于某种原因,当我试图使用operator []
插入时,它崩溃了。该类用于保存二进制数据的缓冲区,其长度由成员m_nLen
表示。
代码如下:
class SomeKeyClass
{
public:
unsigned char m_buffer[ SOME_LENGTH_CONSTANT ];
size_t m_nLen;
public:
inline SomeKeyClass( const unsigned char * data, size_t nLen )
{
m_nLen = min( SOME_LENGTH_CONSTANT, nLen );
memcpy( m_buffer, data, m_nLen );
}
inline SomeKeyClass( const SomeKeyClass& oKey )
{
*this = oKey;
}
inline bool operator < ( const SomeKeyClass& oKey ) const
{
return memcmp( m_buffer, oKey.m_buffer, min( m_nLen, oKey.m_nLen ) ) < 0;
}
inline SomeKeyClass & operator = ( const SomeKeyClass& oKey )
{
memcpy( m_buffer, oKey.m_buffer, oKey.m_nLen );
return *this;
}
};
这门课有什么问题吗?我可以使用std::string<unsigned char>
使用二进制数据作为密钥吗?
问题是您没有在复制构造函数或赋值操作符中设置m_nLen
成员。因此,每当您使用具有未初始化或错误的m_nLen
值的对象时,事情可能会出错,导致可能的崩溃(通常,未定义行为)。
在实现用户定义的复制构造函数和赋值操作符时,应该努力确保最后输出的是所讨论对象的实际副本(引用计数对象是一种特殊情况,但它仍然意味着正在进行复制)。否则,产生不完整或错误对象副本的程序非常脆弱,并且是调试的可怕负担。
请看Paul McKenzie的答案,看看它崩溃的原因。
这门课有什么问题吗?
是的,你的operator<
坏了。
考虑你有一个键"abc"和另一个键"abcd"的情况,你的小于运算符会说它们是等价的,因为你只测试前3个字符。
一个正确的实现需要在memcmp
说它们相等的时候比较长度,因为memcmp
调用不一定比较完整的字符串:
bool operator<(const SomeKeyClass& oKey) const
{
const std::size_t len = std::min(m_nLen, oKey.m_nLen);
if (len > 0)
{
const int cmp = memcmp(m_buffer, oKey.m_buffer, len);
if (cmp != 0)
return cmp < 0;
}
return m_nLen < oKey.m_nLen;
}
相关文章:
- C++尝试深度复制唯一指针时出现内存访问冲突
- C++中的内存分配(引发异常:读取访问冲突)
- 在尝试使用CUDA分配内存时,我遇到了访问冲突写入位置错误
- 使用加速进程间创建消息队列 - 内存访问冲突
- C 指针转换会导致内存访问冲突
- 为什么创建进程 API 调用会导致内存访问冲突?
- 访问共享内存时出现读取访问冲突
- 这Microsoft CFileDialog 示例是否会导致潜在的内存冲突
- Python C++扩展 - 内存泄漏或访问冲突
- 如何修复<程序名称>中的"<内存位置>未处理的异常。Visual Studio 2017 中的访问冲突写入位置<内存位置>"
- C 程序内存冲突依赖于 std::cout (?)
- 使用 std::map 作为本地成员的内存访问冲突
- 编译哈希算法时出现内存访问冲突错误
- 使用内存访问冲突错误
- 堆栈引发内存访问冲突
- 使用 Boost::序列化时内存访问冲突
- 调用std::vector::empty()时内存访问冲突读取位置
- 简单加密程序集程序-写入内存位置时发生访问冲突
- 动态分配内存时发生访问冲突
- 修复 std::map 中的冲突内存泄漏