我们的 c++ DLL 代码部分在 Windows 7 SP1 上崩溃 运行

Section of the code of our c++ DLL crashes wen ran on a Windows 7 SP1

我正在开发一个使用 Air Native Extension (ANE) 的桌面 Air 应用程序。 ANE 的本机部分仅由部分用 C 和部分用 C++ 编写的 DLL 组成。该应用程序是使用 Visual Studio 2010 编译的,需要 MSVCR100.DLL 和 MSVCP100.DLL 与应用程序的 exe 文件位于同一目录中。

该应用程序和 DLL 在许多计算机上运行良好,但在干净的 Windows 7 SP1 计算机上,其部分代码会导致 DLL 崩溃。

我已将冲突代码缩小为以下内容:

// Addresses.
String^ defaultGateway = "Not Found";
String^ interfaceIPAddress = "Not Found";
String^ interfaceMask = "Not Found";

array<NetworkInterface^>^nics = NetworkInterface::GetAllNetworkInterfaces();
if (nics != nullptr || nics->Length > 0)
{
    System::Collections::IEnumerator^ myEnum4 = nics->GetEnumerator();
    while (myEnum4->MoveNext())
    {
        NetworkInterface^ adapter = safe_cast<NetworkInterface ^>(myEnum4->Current);
        IPInterfaceProperties^ properties = adapter->GetIPProperties();

        GatewayIPAddressInformationCollection^ gateways = properties->GatewayAddresses;
        for each (GatewayIPAddressInformation^ gateway in gateways)
        {
            if (gateway->Address->AddressFamily == AddressFamily::InterNetwork)
            {
                defaultGateway = gateway->Address->ToString();
                for each (UnicastIPAddressInformation^ unicastIPAddressInformation in properties->UnicastAddresses)
                {
                    if (unicastIPAddressInformation->Address->AddressFamily == AddressFamily::InterNetwork)
                    {
                        interfaceIPAddress = unicastIPAddressInformation->Address->ToString();
                        interfaceMask = unicastIPAddressInformation->IPv4Mask->ToString();
                    }
                }
            }
        }
    }
}

只是为了给你更多的上下文,我将复制整个函数,代码是:

FREObject MainInterfaceInfo(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[])
{
    // Addresses.
    String^ defaultGateway = "Not Found";
    String^ interfaceIPAddress = "Not Found";
    String^ interfaceMask = "Not Found";

    array<NetworkInterface^>^nics = NetworkInterface::GetAllNetworkInterfaces();
    if (nics != nullptr || nics->Length > 0)
    {
        System::Collections::IEnumerator^ myEnum4 = nics->GetEnumerator();
        while (myEnum4->MoveNext())
        {
            NetworkInterface^ adapter = safe_cast<NetworkInterface ^>(myEnum4->Current);
            IPInterfaceProperties^ properties = adapter->GetIPProperties();

            GatewayIPAddressInformationCollection^ gateways = properties->GatewayAddresses;
            for each (GatewayIPAddressInformation^ gateway in gateways)
            {
                if (gateway->Address->AddressFamily == AddressFamily::InterNetwork)
                {
                    defaultGateway = gateway->Address->ToString();
                    for each (UnicastIPAddressInformation^ unicastIPAddressInformation in properties->UnicastAddresses)
                    {
                        if (unicastIPAddressInformation->Address->AddressFamily == AddressFamily::InterNetwork)
                        {
                            interfaceIPAddress = unicastIPAddressInformation->Address->ToString();
                            interfaceMask = unicastIPAddressInformation->IPv4Mask->ToString();
                        }
                    }
                }
            }
        }
    }

    String^ result = interfaceIPAddress + ";" + interfaceMask + ";" + defaultGateway;

    // Converting the response to const uint8_t *
    msclr::interop::marshal_context oMarshalContext;
    const char* charResponse = oMarshalContext.marshal_as<const char*>(result);
    const uint8_t * resultNativeCharArray = (const uint8_t *)charResponse;
    uint32_t resultNativeCharArrayLength = 0;

    while (true) {
        if (NULL == resultNativeCharArray[resultNativeCharArrayLength]) {
            break;
        }
        else {
            resultNativeCharArrayLength++;
        }
    }

    FREObject functionResult;
    FRENewObjectFromUTF8(resultNativeCharArrayLength, resultNativeCharArray, &functionResult);

    return functionResult;
}

我是 C 和 C++ 的菜鸟,因为 10 年前我只见过几次,所以我不知道究竟是什么导致了 DLL 崩溃。有人可以告诉吗?任何建议将不胜感激。

已编辑

我开始意识到相同的缩小代码使应用程序需要 MSVCR100.DLL 和 MSVCP100.DLL。如果我删除那部分代码,应用程序可以 运行 没有它们。

MSVCP100.DLL 包含标准 C++ 库; MSVCR100.DLL 是 C 运行时。可能类似于 safe_cast 调用引入了依赖关系。有关运行时库的更多详细信息 here.

我建议使用官方可再发行包来部署 Visual C++ 运行时 DLL,而不是自己将它们部署到您的应用程序目录中。有关详细信息,请参阅 Redistributing Visual C++ Files...其中的演练链接将对您有所帮助。这是确保目标系统具有您需要的所有依赖项的可靠方法。您较旧的(非干净的)Win7 系统可能有一些其他应用程序或 Windows 更新安装为您重新分发,这就是您的代码在那里工作的原因。

实际上,搞砸一切的代码行是:

interfaceMask = unicastIPAddressInformation->IPv4Mask->ToString();

如果删除该行,DLL 将 运行 没有问题。

出现此问题是因为系统的 不活动 网络接口之一在 gateway->Address->ToString() 上报告了“0.0.0.0”。因此,当尝试 unicastIPAddressInformation->IPv4Mask->ToString() 时,DLL 会崩溃。

为了解决这个问题,我只是在开头添加了一个 if (adapter->OperationalStatus == OperationalStatus::Up),之后一切正常。结果代码如下:

while (myEnum4->MoveNext())
    {
        NetworkInterface^ adapter = safe_cast<NetworkInterface ^>(myEnum4->Current);
        IPInterfaceProperties^ properties = adapter->GetIPProperties();

        if (adapter->OperationalStatus == OperationalStatus::Up)
        {
            GatewayIPAddressInformationCollection^ gateways = properties->GatewayAddresses;
            for each (GatewayIPAddressInformation^ gateway in gateways)
            {
                if (gateway->Address->AddressFamily == AddressFamily::InterNetwork)
                {
                    defaultGateway = gateway->Address->ToString();
                    for each (UnicastIPAddressInformation^ unicastIPAddressInformation in properties->UnicastAddresses)
                    {
                        if (unicastIPAddressInformation->Address->AddressFamily == AddressFamily::InterNetwork)
                        {
                            interfaceIPAddress = unicastIPAddressInformation->Address->ToString();
                            interfaceMask = unicastIPAddressInformation->IPv4Mask->ToString();
                        }
                    }
                }
            }
        }
    }