在winhttp.dll中的访问冲突
Access violation in winhttp.dll
我试图在c++中使用WinHTTP执行HTTP GET,但在解析名称后的某个时刻崩溃(在状态回调函数中获得WINHTTP_CALLBACK_STATUS_NAME_RESOLVED后)。我在winhttp.dll中遇到访问冲突。调用栈是:
winhttp.dll!HTTP_USER_REQUEST::_IndicateSocketAddress() + 0x221ed bytes
HTTP_USER_REQUEST:: ondnsnamerresolved () + 0x24 bytes
WEBIO_REQUEST::_OnInformation() + 0x1c0c字节_WaIndicateHttpRequestInformation@16() + 0x15a字节_WaHttpInformationConnection@16() + 0x7a字节
_WapTcpDnsQueryCompletionRoutine@12() + 0x2f bytes
_WapCallDnsQueryCompletion@12() + 0x6d字节_WaDnsResolutionWorker@8() + 0x157字节ntdll.dll!_TppSimplepExecuteCallback@8() + 0x7b字节
ntdll.dll!TppWorkerThread@4() + 0x5a4 bytes
@BaseThreadInitThunk@12() + 0x12字节
__RtlUserThreadStart@8() + 0x27字节
ntdll.dll!__RtlUserThreadStart@8() + 0x1b bytes
相关代码为:
enum OnlineState
{
OnlineState_Idle,
OnlineState_Registering
};
static OnlineState g_OnlineState = OnlineState_Idle;
HINTERNET g_Request = 0;
HINTERNET g_Connection = 0;
unsigned char g_HTTPBuffer[1024];
void HTTPRequestComplete()
{
if(g_Request != 0)
{
WinHttpCloseHandle(g_Request);
g_Request = 0;
}
if(g_Connection != 0)
{
WinHttpCloseHandle(g_Connection);
g_Connection = 0;
}
g_OnlineState = OnlineState_Idle;
}
void HTTPAsyncCallback(HINTERNET hInternet, DWORD_PTR dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInformation, DWORD dwStatusInformationLength)
{
switch(dwInternetStatus)
{
case WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE:
{
// Get the response
if (!WinHttpReceiveResponse(g_Request, 0))
{
// Failed to get the response
HTTPRequestComplete();
return;
}
}
break;
case WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE:
{
DWORD statusCode = 0;
DWORD statusCodeSize = sizeof(DWORD);
if (!WinHttpQueryHeaders(g_Request,
WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
WINHTTP_HEADER_NAME_BY_INDEX,
&statusCode,
&statusCodeSize,
WINHTTP_NO_HEADER_INDEX))
{
// Failed to query headers
HTTPRequestComplete();
return;
}
if (HTTP_STATUS_OK != statusCode)
{
// Error status
HTTPRequestComplete();
return;
}
if (!WinHttpReadData(g_Request,
g_HTTPBuffer,
sizeof(g_HTTPBuffer),
0))
{
// Error reading data
HTTPRequestComplete();
return;
}
}
break;
case WINHTTP_CALLBACK_STATUS_READ_COMPLETE:
{
if (dwStatusInformationLength > 0)
{
// Store the data
// Read the next data
if (!WinHttpReadData(g_Request,
g_HTTPBuffer,
sizeof(g_HTTPBuffer),
0))
{
// Error
HTTPRequestComplete();
return;
}
}
else
{
// Request completed OK
HTTPRequestComplete();
}
}
break;
default:
break;
}
}
// Online functionality
void Online_UpdateServer()
{
switch(g_OnlineState)
{
case OnlineState_Idle:
{
// Get our local ip address by connecting a local socket to a web address and reading the socket name
// Look up the address to connect to
addrinfo hints;
addrinfo* res = 0;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
getaddrinfo("www.google.com", "80", &hints, &res);
// Create the socket
int tempSocket = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
unsigned int localAddress = 0;
if (tempSocket >= 0)
{
// Connect the socket
connect(tempSocket, res->ai_addr, res->ai_addrlen);
// Get the socket name (our local ip address)
sockaddr_in localName;
memset(&localName, 0, sizeof(localName));
int bufferSize = sizeof(localName);
if(getsockname(tempSocket, (sockaddr*)&localName, &bufferSize) == 0)
{
// Get the IP address
localAddress = localName.sin_addr.S_un.S_addr;
}
closesocket(tempSocket);
}
// Connect
g_Connection = WinHttpConnect(g_Internet, L"www.google.com", INTERNET_DEFAULT_PORT, 0);
// Open the request
std::wstringstream urlString;
urlString << L"/";
std::wstring tempString = urlString.str();
const wchar_t* wurlString = tempString.c_str();
g_Request = WinHttpOpenRequest(g_Connection, 0, wurlString, 0, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
// Install the status callback function.
if(WINHTTP_INVALID_STATUS_CALLBACK == WinHttpSetStatusCallback(g_Request, (WINHTTP_STATUS_CALLBACK)HTTPAsyncCallback, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, NULL))
{
OutputDebugString(L"Error");
}
// Send the request
if(!WinHttpSendRequest(g_Request, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0))
{
OutputDebugString(L"Error");
}
// Log that we're registering
g_OnlineState = OnlineState_Registering;
}
break;
case OnlineState_Registering:
{
// Don't do anything, as we're currently registering
}
break;
default:
break;
}
}
g_Internet是这样初始化的:
// Initialise HTTP
g_Internet = WinHttpOpen(L"Boomba", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, WINHTTP_FLAG_ASYNC);
据我所知,我正在初始化和正确使用WinHTTP,一切似乎都没有错误。回调被调用两次,第一次与WINHTTP_CALLBACK_STATUS_RESOLVING_NAME,然后与WINHTTP_CALLBACK_STATUS_NAME_RESOLVED,然后我得到一个访问冲突:
0xC0000005:访问冲突读取位置0x00000014
位置变化,到各种各样的事情,所以我认为它看起来可能是一个线程问题,但我不确定什么可能是问题。什么好主意吗?(我用的是64位的Windows 7)
if (WINHTTP_INVALID_STATUS_CALLBACK == WinHttpSetStatusCallback(
g_Request,
(WINHTTP_STATUS_CALLBACK)HTTPAsyncCallback, // <=== evil
WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS,
NULL))
编译器最初抱怨函数与所需的函数指针类型不匹配。您可以通过关闭编译器来解决该问题。但这并没有真正解决问题。现在你给自己买了一个真正的问题,一个损坏的堆栈。很难诊断
回调函数必须声明为__stdcall,而不是默认的__cdecl调用约定。Windows头使用CALLBACK宏。解决办法:
void CALLBACK HTTPAsyncCallback(/* etc*/)
当然还要去掉强制转换
- 在类 12.exe 中0x7B37FF80 (ucrtbased.dll) 引发异常: 0xC0000005:访问冲突读
- 从Delphi调用C++DLL时发生访问冲突
- 在 DLL 中嵌入 Python:Py_DECREF列表对象时访问冲突读取位置
- 将 std::string 作为参数从一个 DLL 传递到另一个 DLL 引发访问冲突错误
- 如果使用低于 VS2015 的 vc++ 编译器版本编译,则 DLL 中的访问冲突
- Windows错误:异常:使用从C++到Python的ctypes创建DLL时出现访问冲突或Windows错误193
- C++ python 中的函数来自使用 ctypes 的.dll - 找不到函数和访问冲突
- 使用参数的 C# 委托回调会导致从 DLL 调用时C++访问冲突
- 实验室中0x6BE20E11 (ucrtbased.dll) 的未处理异常.exe: 0xC0000005:访问冲突读取
- 将静态库转换为 DLL 会导致在 main 之前出现访问冲突
- 在 "<name>.exe" 中0x00007FFF168E1657 (vcruntime140d.dll) 引发异常:0xC0000005:访问冲突写入位置0x0000000000000
- 从C#返回调用C++dll函数的值时发生访问冲突
- OpenGL:glDrawArrays()引发异常(nvoglv32.dll)读取位置0x00000000时发生访问冲突
- C# 到非托管 C++ DLL 访问冲突/"frame not in module"
- 使用boost::signals2并卸载DLL时发生访问冲突
- VkLayer_param_checker.dll访问冲突
- 注入DLL的函数中出现访问冲突异常(5)
- 使用 DLL 中的C++函数进行访问冲突
- 将 LPTSTR 参数传递给 DLL 会在项目中C++出现访问冲突
- 在 .Net 应用程序中调用 C++ DLL 时出现系统访问冲突异常