gpt4 book ai didi

c++ - 通过 WinAPI 套接字连接到蓝牙设备时崩溃(访问冲突读取位置 0x00000004)

转载 作者:塔克拉玛干 更新时间:2023-11-03 06:58:16 24 4
gpt4 key购买 nike

我觉得你是我最后的希望。我有一个蓝牙设备(更准确地说是一个传感器),我想连接它并从中读取数据。该设备提供 SPP(串行端口配置文件)。为了避免蓝牙地址和虚拟串行端口(COM 端口)的可靠映射问题,我将使用套接字。

不幸的是,应用程序总是在从 WinAPI 函数 connect(...) 返回之前崩溃:0xC0000005:访问冲突读取位置 0x00000004,所以我得到 no错误代码

但是,这很奇怪,当我右键单击蓝牙系统托盘图标以显示可用设备时,我的设备显示正在通过身份验证和连接。此列表之前是空的,类(class)。

我的操作系统是 Windows 7 64 位,IDE 是 Visual Studio 2010,Microsoft Bluetooth Stack。查找并连接到我唯一设备的代码:

#include <iostream>
#include <string>
#include <algorithm>
#include <cassert>

#define WIN32_LEAN_AND_MEAN

#include <Windows.h>
#include <BluetoothAPIs.h>
#include <Winsock2.h>
#include <Ws2bth.h>



BOOL auth_callback_ex(LPVOID pvParam, PBLUETOOTH_AUTHENTICATION_CALLBACK_PARAMS authParams)
{
BLUETOOTH_AUTHENTICATE_RESPONSE response;
response.bthAddressRemote = authParams->deviceInfo.Address;
response.authMethod = authParams->authenticationMethod; // == BLUETOOTH_AUTHENTICATION_METHOD_LEGACY

UCHAR pin[] = "1234";
std::copy(pin, pin+sizeof(pin), response.pinInfo.pin);
response.pinInfo.pinLength = sizeof(pin)-1; //excluding '\0'

response.negativeResponse = false;


HRESULT err = BluetoothSendAuthenticationResponseEx(NULL, &response);
if (err)
{
std::cout << "BluetoothSendAuthenticationResponseEx error = " << err << std::endl;
}

return true;
}


int main()
{
BLUETOOTH_DEVICE_SEARCH_PARAMS btSearchParams;

btSearchParams.dwSize = sizeof(BLUETOOTH_DEVICE_SEARCH_PARAMS);
btSearchParams.cTimeoutMultiplier = 5; //5*1.28s search timeout
btSearchParams.fIssueInquiry = true; //new inquiry

//return all known and unknown devices
btSearchParams.fReturnAuthenticated = true;
btSearchParams.fReturnConnected = true;
btSearchParams.fReturnRemembered = true;
btSearchParams.fReturnUnknown = true;

btSearchParams.hRadio = NULL; //search on all local radios



BLUETOOTH_DEVICE_INFO btDeviceInfo;
ZeroMemory(&btDeviceInfo, sizeof(BLUETOOTH_DEVICE_INFO)); //"initialize"

btDeviceInfo.dwSize = sizeof(BLUETOOTH_DEVICE_INFO);

HBLUETOOTH_DEVICE_FIND btDeviceFindHandle = NULL;

btDeviceFindHandle = BluetoothFindFirstDevice(&btSearchParams, &btDeviceInfo);
if(btDeviceFindHandle)
{

HBLUETOOTH_AUTHENTICATION_REGISTRATION authCallbackHandle = NULL;

DWORD err = BluetoothRegisterForAuthenticationEx(&btDeviceInfo, &authCallbackHandle, &auth_callback_ex, NULL);


if (err != ERROR_SUCCESS)
{
DWORD err = GetLastError();
std::cout << "BluetoothRegisterForAuthentication Error" << err << std::endl;
}

/////////////// Socket
WSADATA wsaData;
err = WSAStartup(MAKEWORD(2,2), &wsaData);
if (err)
{
std::cout << "WSAStartup error = " << err << std::endl;
}


// create BT socket
SOCKET s = socket (AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
assert(s != INVALID_SOCKET); //WSAGetLastError //throw // runtime check release?

SOCKADDR_BTH btSockAddr;
btSockAddr.addressFamily = AF_BTH;
btSockAddr.btAddr = btDeviceInfo.Address.ullLong;
btSockAddr.serviceClassId = RFCOMM_PROTOCOL_UUID; //SerialPortServiceClass_UUID (no difference)
btSockAddr.port = BT_PORT_ANY;


err = connect(s, reinterpret_cast<SOCKADDR*>(&btSockAddr), sizeof(SOCKADDR_BTH));

/* <--- never got so far --> */

if (err)
{
DWORD wsaErr = WSAGetLastError();
std::cout << "connect error = " << wsaErr << std::endl;

}
else
{
//err = shutdown(s, SD_BOTH);

err = closesocket(s);
if (err)
{
std::cout << "closesocket error = " << err << std::endl;
}
}

WSACleanup();
///////////////Socket


BOOL ok = BluetoothUnregisterAuthentication(authCallbackHandle);
if (!ok)
{
DWORD err = GetLastError();
std::cout << "BluetoothUnregisterAuthentication Error" << err << std::endl;
}



ok = BluetoothFindDeviceClose(btDeviceFindHandle);
if (!ok)
{
DWORD err = GetLastError();
std::cout << "BluetoothDeviceClose Error" << err << std::endl;
}
}
else
{
DWORD err = GetLastError();
std::cout << "BluetoothFindFirstDevice Error" << err << std::endl;
}


std::cin.get();
}

我做了一些更多的观察:

  • 身份验证回调和 BluetoothSendAuthenticationResponseEx 函数工作正常,没有返回任何错误。
  • 如果我没有安装身份验证回调 (BluetoothRegisterForAuthenticationEx),因此必须手动输入 PIN(尝试连接时 UI 会自动显示),connect 函数正常返回,一切正常,也是。我什至得到了数据(这段代码中省略了 recv 部分)。
  • 如果我完全手动搜索和配对(蓝牙托盘图标 -> 添加设备),一切也都很好。安装了服务和虚拟串口。数据来自腻子。

所以在调用身份验证回调和结束 connect 函数之间的某个地方出了问题。也许当尝试通过指针获取某个结构数据时,该指针不应为 NULL,加上偏移量。

还是我做错了什么?有什么东西不见了吗?谢谢...

最佳答案

问题是您的函数使用了错误的调用约定。 According to MSDN, you need to use the CALLBACK macro ,如:

BOOL CALLBACK auth_callback_ex(LPVOID pvParam, PBLUETOOTH_AUTHENTICATION_CALLBACK_PARAMS authParams)

错误的调用约定将导致返回时堆栈不匹配,这可能会在无法找到其局部变量时导致 MS 蓝牙代码内部的访问冲突。

否则它可能会导致函数的参数全部困惑。如果 authParamspvParam 被交换,因为 cdecl 调用约定期望 args 从右到左推送,而 stdcall 推送它们从左到右,您将在 authParams 中得到 NULL,然后 authParams->deviceInfo.Address 将尝试读取地址 0x04

编译器应该已经捕捉到了这一点。编译时打开最大警告 (/W4)。你必须忽略关于未知编译指示的警告,这是一个 bug in the header which I'm reporting to Microsoft (misspelled #pragma deprecated) .

不幸的是有 a second bug in the header, much more serious, of not specifying the calling convention explicitly ,结果是如果使用 /Gz,它只能在 x86(32 位代码)上正常工作。呸!


跟进:在 VS2013 附带的 SDK header 中,这两个问题都已修复。

关于c++ - 通过 WinAPI 套接字连接到蓝牙设备时崩溃(访问冲突读取位置 0x00000004),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6556860/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com