将结构体复制到map数组元素时触发访问违规的问题排查与解决
问题解决与验证方案
错误原因分析
你遇到的访问违规核心原因是:std::map<int, hdr(*)[20]> SP; 定义的map值类型是指向20个hdr结构体的数组的指针,当通过SP[0]访问键为0的元素时,map会自动插入一个默认构造的指针值——而指针类型的默认值是nullptr(空指针)。此时SP[0][0]相当于对空指针做解引用操作,直接触发内存访问违规。
问题1:解决访问违规的方法
需要为map中的每个键值对分配实际的数组内存,具体操作如下:
- 访问map的键时,先检查该键是否存在;若不存在,用
new分配一块能容纳20个hdr的数组内存,再将指针存入map。 - 确保后续操作的是已分配有效内存的指针。
修改后的示例代码:
#include <iostream> #include <map> #include <cstring> int main() { struct hdr { int cpi_length = 42; }; hdr* this_hdr = new hdr; // 改用hdr*而非void*,提升类型安全性 std::map<int, hdr(*)[20]> SP; // 检查键0是否存在,不存在则分配内存 if (SP.find(0) == SP.end()) { SP[0] = new hdr[20]; // 分配20个hdr的数组,返回的指针符合hdr(*)[20]类型 } std::cout << sizeof(hdr) << std::endl; // 输出4 std::cout << sizeof(this_hdr) << std::endl; // 输出当前平台指针大小(如4或8) std::cout << sizeof(SP[0][0]) << std::endl; // 输出80(20*4) // 此时SP[0][0]指向有效内存,可安全执行memcpy std::memcpy(SP[0][0], this_hdr, sizeof(hdr)); std::cout << SP[0][0]->cpi_length << std::endl; // 输出42,验证复制成功 // 释放内存避免泄漏 delete this_hdr; delete[] SP[0]; SP.clear(); return 0; }
问题2:验证功能实现的方法
可以通过以下几种方式验证复制操作是否符合预期:
- 直接打印成员值:打印目标缓冲区中结构体的
cpi_length成员,确认其值与源对象一致(比如示例中的42)。 - 内存内容对比:使用
std::memcmp比较源对象和目标缓冲区的内存内容,返回值为0则说明内存完全一致:if (std::memcmp(SP[0][0], this_hdr, sizeof(hdr)) == 0) { std::cout << "内存复制成功" << std::endl; } - 检查目标地址有效性:判断
SP[0]是否为nullptr,确保操作的是有效内存空间。
内容的提问来源于stack exchange,提问作者Nathan Goedeke
相关产品推荐
相关产品推荐

