我们的 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();
}
}
}
}
}
}
我正在开发一个使用 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();
}
}
}
}
}
}