如何解决Google Test中读取内存地址时的访问违例问题?
问题原因分析
你遇到的0xC0000005访问违例错误,核心原因是直接在用户态测试程序中访问硬件物理地址0x2025111B:
- 该地址属于硬件寄存器的物理地址,在普通PC的用户态进程中,这个地址并未映射到进程的虚拟地址空间,操作系统会直接阻止这种非法内存访问,触发权限错误。
- 即便你是在做嵌入式开发,当在PC上运行Google Test时,也没有对应的硬件设备提供这个寄存器,自然无法对该地址进行读写操作。
解决办法
1. 重构代码,用依赖注入解耦硬件操作
把直接访问寄存器的逻辑封装成可替换的接口,避免硬编码物理地址,这样测试时可以用模拟对象替代真实硬件操作。
重构后的核心代码:
// 定义寄存器操作接口 class RegAccessor { public: virtual void setBit(uint32_t bit) = 0; virtual ~RegAccessor() = default; }; // 真实硬件场景的实现 class HardwareRegAccessor : public RegAccessor { public: void setBit(uint32_t bit) override { volatile MYREG_t* reg = reinterpret_cast<volatile MYREG_t*>(0x2025111BUL); reg->u32reg |= bit; } }; // 原业务逻辑依赖接口,不再直接操作硬件地址 void testcode(RegAccessor& accessor) { accessor.setBit(SET_VALUE); call_another_funct(); }
配套Google Mock测试用例:
#include <gmock/gmock.h> class MockRegAccessor : public RegAccessor { public: MOCK_METHOD(void, setBit, (uint32_t bit), (override)); }; TEST_F(sample_test, check) { MockRegAccessor mock; EXPECT_CALL(mock, setBit(SET_VALUE)).Times(1); testcode(mock); }
2. 临时映射模拟寄存器内存(仅简单场景适用)
如果不想大规模重构代码,可以在测试前将目标地址映射到进程可访问的内存区域(以Windows为例):
#include <Windows.h> TEST_F(sample_test, check) { // 分配内存并映射到目标地址,仅用于测试 void* mappedAddr = VirtualAlloc(reinterpret_cast<void*>(0x2025111B), sizeof(MYREG_t), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); ASSERT_NE(mappedAddr, nullptr) << "内存映射失败"; testcode(); // 测试完成后清理 VirtualFree(mappedAddr, 0, MEM_RELEASE); }
注意:这种方式受操作系统地址空间布局限制,不是所有地址都能成功映射,且仅能验证读写逻辑,无法模拟硬件的真实行为。
3. 嵌入式场景:使用硬件模拟器
如果是嵌入式开发场景,推荐用QEMU等硬件模拟器运行测试,让测试程序在模拟的硬件环境中执行,此时0x2025111B地址会被模拟器映射到虚拟硬件寄存器,避免访问违例。
内容的提问来源于stack exchange,提问作者user2986042
相关产品推荐
相关产品推荐

