在 DLL 中捕获未处理的异常

Catching unhanded exceptions in a DLL

我正在 .dll 项目中使用 Visual Studio Express 2013 编写 C++ 套接字代码。我正处于此 sendto 函数出错的地步:

/* Send data back */
            if (sendto(sd, (const char *)sendBuffer,(int)sizeof(sendBuffer), 0,
                (struct sockaddr *)&client, sizeof(client)) ==
                SOCKET_ERROR)
            {
                err = WSAGetLastError();
                closesocket(sd);
                WSACleanup(); 
                throw std::runtime_error("Error sending datagram.");


            }

我知道我们可以使用 WSAGetLastError() 获得错误代码,但如果我将其初始化为变量,我似乎只会得到垃圾数字。如何提取 sendto 错误?我编写了单元测试来测试这个 dll,但我不确定是否有办法打印出错误。

编辑:所以在将条件更改为 == not != 后,它不再在 sendto 处失败,但现在在

处失败
bytes_received = recvfrom(sd, readBuffer, NTP_PACKET_MAX, 0, (struct sockaddr *)&client, &len);

            if (bytes_received == SOCKET_ERROR)
            {
                err = WSAGetLastError(); 
                closesocket(sd);
                WSACleanup();
                throw std::runtime_error("Could not receive datagram.");
            }

和原来的问题一样,我不确定如何得到正确的错误。调试 recvfrom 函数时,我将鼠标悬停在 err 上,它表示它保存的值为 114351196。据我所知,这不是有效的 Windows 套接字错误代码。

你的代码中有几个严重的错误

        /* Send data back */
        if (sendto(sd, (const char *)sendBuffer,(int)sizeof(sendBuffer), 0,
            (struct sockaddr *)&client, sizeof(client)) !=
            SOCKET_ERROR) // SHOULD BE == (1)
        {
            throw std::runtime_error("Error sending datagram.");
            // UNREACHABLE CODE (2)
            closesocket(sd);
            WSACleanup();
        }

错误1:发送成功时进入了您的错误块。这可能意味着您的错误未初始化(如果不是,它将是来自其他地方的最后一个错误值)。根据 WSAGetLastError 的 MSDN 文档,应在 WinSocket 操作失败后立即调用该函数,并且仅在这些情况下。

如果您在(您正在执行的)操作成功后调用它,则无法保证您将收到什么值。如果可能是此线程上另一个 WinSocket 操作的最后一个错误,则它可能是 0,也可能是其他值。文档没有说明如果在没有操作失败时检索到错误会发生什么,因此您可以将此视为未定义的行为。

错误 2:抛出异常后,函数将立即退出。您不会调用 closesocketWSACleanup

更新:

我猜您是在为 err 赋值之前在调试器中检查它的值。你应该按照以下方式做一些事情:

bytes_received = recvfrom(sd, readBuffer, NTP_PACKET_MAX, 0, (struct sockaddr *)&client, &len);
if (bytes_received == SOCKET_ERROR)
{
    int err = WSAGetLastError(); 
    // In debugger you must be here before err is set
    closesocket(sd);
    WSACleanup();
    std::string what{"Could not receive datagram."};
    what+= std::to_string(err);
    throw std::runtime_error(what.c_str());
}