WinHTTP异步回调context无效、WinHttpReceiveResponse返回错误码6求助
问题根因分析
- context字段取值异常的核心原因:你使用
std::vector<connection_context>存储上下文对象,std::vector在动态扩容时会重新分配整块内存,原有存储元素的内存地址会全部失效。你调用WinHttpSendRequest时传入的是&contexts.back()这个临时地址,后续循环继续push_back触发扩容后,之前传给WinHTTP的所有context指针全部指向无效内存,自然读取不到正确的字段值。 - 错误码6(无效句柄)的核心原因:
connection_context结构体中的read_complete事件句柄没有初始化,你没有调用CreateEvent创建事件对象,WaitForSingleObject会立刻返回错误,代码直接执行WinHttpCloseHandle(contexts[i].request_handle)关闭请求句柄。此时异步回调才开始执行,访问已经被关闭的request_handle自然触发无效句柄错误。
修复方案
- 解决context地址失效问题:
方案一:预先给vector分配足够容量,避免运行时扩容:在循环前调用contexts.reserve(ggs_get_aobs.size())
方案二:改用std::list<connection_context>存储上下文,list的元素插入删除不会改变原有元素的内存地址
方案三:使用堆分配存储context:每个上下文用new connection_context创建,等请求完全结束后再delete释放,避免内存泄漏 - 初始化事件句柄:
每个connection_context对象创建时,添加初始化逻辑:
所有请求处理完成后,调用contexts.back().read_complete = CreateEvent(NULL, FALSE, FALSE, NULL);CloseHandle释放事件句柄,避免句柄泄漏 - 调整资源释放逻辑:
不要在WaitForSingleObject返回后立刻关闭请求句柄,建议增加请求完成标记,确认所有回调逻辑执行完毕后再释放请求句柄、context等资源,避免回调执行时访问已经释放的资源 - 请求体传参优化:
WinHttpSendRequest的请求体长度参数不需要+1,直接传入contexts.back().request_payload.size()即可,额外多传的\0会被当成请求体的一部分发送给服务端,可能导致服务端解析异常。
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

