如何从VT_DISPATCH类型的SAFEARRAY中获取有效IDispatch指针?
问题原因与解决方案
你的代码崩溃的核心原因是类型转换错误:当SAFEARRAY的元素类型为VT_DISPATCH时,每个元素存储的是IDispatch*指针,而SafeArrayPtrOfIndex返回的pData是指向该元素的指针(即IDispatch**类型)。你直接将pData强制转换为IDispatch*,相当于对指针的内存地址调用AddRef,而非真正的IDispatch对象,必然触发访问异常。
正确示例代码
if (vtS == VT_DISPATCH) { IDispatch* iDisp = NULL; IDispatch** ppDisp = NULL; HRESULT ret = S_OK; // 假设idx是一维数组的有效索引(指向LONG类型的索引变量) if (idx) { // 将pData转为IDispatch**类型,而非直接转IDispatch* ret = SafeArrayPtrOfIndex(SA, idx, reinterpret_cast<void**>(&ppDisp)); if (FAILED(ret)) { goto CleanUp; } // 解引用得到真正的IDispatch指针 iDisp = *ppDisp; } else { // 可选:若取一维数组第一个元素,也可使用SafeArrayGetElement LONG firstIdx = 0; ret = SafeArrayGetElement(SA, &firstIdx, &iDisp); if (FAILED(ret)) { goto CleanUp; } } // 必须先检查指针非空,再调用AddRef if (iDisp) { iDisp->AddRef(); pVGet->vt = VT_DISPATCH; pVGet->pdispVal = iDisp; } else { // 处理空指针情况,避免无效赋值 pVGet->vt = VT_NULL; } CleanUp: // 无需手动解锁数组,SafeArrayPtrOfIndex内部已自动处理锁定/解锁 // 若有其他资源需释放,在此添加逻辑 }
关键注意事项
- 类型匹配:
SafeArrayPtrOfIndex返回的是元素的地址,需根据SAFEARRAY元素类型匹配指针类型(VT_DISPATCH对应IDispatch**)。 - 空指针检查:调用
AddRef前必须确认iDisp不为NULL,否则会触发空指针访问异常。 - 引用计数管理:SAFEARRAY中的
IDispatch*指针不会自动增加引用计数,取出后必须调用AddRef确保对象不会被提前释放;后续不再使用pVGet->pdispVal时,需调用Release释放引用。
内容的提问来源于stack exchange,提问作者René Rössler
相关产品推荐
相关产品推荐

