C++ DLL模拟智能卡重复调用命令返回6700及内存访问无效问题
解决C++智能卡模拟DLL重复调用命令返回空指针的问题
可能的问题根源
- JSON资源生命周期异常:首次调用后,解析JSON的内存对象(如用nlohmann/json、rapidjson等库生成的实例)被提前释放,导致重复调用时指针失效,触发6700空指针错误。
- 命令状态未重置:
CommandHandler类维护的命令序列状态机,在首次调用后未回到初始位置,重复调用初始命令时无法匹配到对应响应映射。 - 文件读写资源错误:重新读写JSON时,文件句柄未正确关闭,或多线程场景下存在资源竞争,引发“Invalid memory access”错误。
具体解决办法
1. 缓存JSON映射,避免重复解析与释放
将JSON解析后的映射结构作为CommandHandler的成员变量,在类初始化时一次性读取解析,后续调用直接复用缓存数据,避免临时对象销毁导致的指针失效:
class CommandHandler { private: nlohmann::json cmdResponseMap; // 成员变量缓存JSON映射 std::mutex jsonMutex; // 多线程场景下加锁保护 public: CommandHandler() { // 初始化时读取并解析JSON文件 std::ifstream jsonFile("cmd_mapping.json"); if (jsonFile.is_open()) { jsonFile >> cmdResponseMap; jsonFile.close(); } } std::vector<uint8_t> sendCommand(const std::vector<uint8_t>& cmd) { // 直接使用缓存的cmdResponseMap匹配响应 std::lock_guard<std::mutex> lock(jsonMutex); // ... 命令匹配与响应生成逻辑 ... } };
2. 重置命令序列状态
在CommandHandler中添加状态重置方法,外部调用方在重复执行命令序列前调用,确保状态机回到初始位置:
class CommandHandler { private: enum class CmdState { INIT, STEP1, STEP2 }; CmdState currentState = CmdState::INIT; public: void resetState() { currentState = CmdState::INIT; // 重置其他关联状态变量 } std::vector<uint8_t> sendCommand(const std::vector<uint8_t>& cmd) { // 根据currentState匹配对应命令分支 // ... 逻辑实现 ... } };
3. 修复JSON重载时的内存访问问题
若需要动态刷新JSON,需加锁保护并确保原子替换映射对象,避免访问已释放的内存:
void CommandHandler::reloadJson() { std::lock_guard<std::mutex> lock(jsonMutex); std::ifstream jsonFile("cmd_mapping.json"); if (!jsonFile.is_open()) { throw std::runtime_error("Failed to open command mapping file"); } nlohmann::json newMap; jsonFile >> newMap; jsonFile.close(); // 显式关闭文件,避免句柄泄漏 cmdResponseMap.swap(newMap); // 原子替换旧映射,避免中间状态的无效访问 }
4. 定位空指针触发点
在sendCommand方法中添加断点或日志,跟踪命令匹配时的指针访问情况,确认是JSON映射指针为空,还是状态机变量失效,精准定位问题后针对性修复。
内容的提问来源于stack exchange,提问作者Pink
相关产品推荐
相关产品推荐

