gpt4 book ai didi

c++ - 代码arp数组、指针和内存分配的不可理解部分(Windows IP函数)

转载 作者:行者123 更新时间:2023-11-28 05:23:08 24 4
gpt4 key购买 nike

我写了一些代码(当然有 mdsm 手动帮助),可以在 arp 表中添加新记录。但我无法理解几行代码。我在开始标记和停止标记之间标记了这些线。我不知道这部分代码的工作原理。如果我删除标记的段落并替换为

的事件
GetIpAddrTable(pIpAddrtable, &dwSize, 0)
GetIpAddrTable(pIpAddrtable, &dwSize, 0)

程序“正确”运行,但一定有什么地方出错了,我想了解是什么以及为什么?我认为这与内存分配有关。

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif


#include <windows.h>
#include <winsock2.h>
#include <ws2ipdef.h>
#include <iphlpapi.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>

#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "ws2_32.lib")
using namespace std;


int main()
{
ULONG ulOutBufLen;
DWORD dwRetVal;

PIP_ADAPTER_INFO pAdapterInfo;

ulOutBufLen = sizeof(IP_ADAPTER_INFO);

pAdapterInfo = (IP_ADAPTER_INFO *) malloc( sizeof(IP_ADAPTER_INFO) );
ulOutBufLen = sizeof(IP_ADAPTER_INFO);

if (GetAdaptersInfo( pAdapterInfo, &ulOutBufLen) != ERROR_SUCCESS) {
free (pAdapterInfo);
pAdapterInfo = (IP_ADAPTER_INFO *) malloc ( ulOutBufLen );
}

if ((dwRetVal = GetAdaptersInfo( pAdapterInfo, &ulOutBufLen)) != ERROR_SUCCESS) {
printf("GetAdaptersInfo call failed with %d\n", dwRetVal);
}


PMIB_IPADDRTABLE pIpAddrtable;
DWORD dwSize = 0;
DWORD dwRetVal2 = 0;
IN_ADDR IPAddr;


free(pIpAddrtable);
pIpAddrtable = (MIB_IPADDRTABLE *) malloc(dwSize*2);




PIP_ADAPTER_INFO pAdapter = pAdapterInfo;

PMIB_IPNETROW pArpEntry;

DWORD ip = inet_addr("182.221.231.1");



//start
if (pIpAddrtable)
{
if (GetIpAddrTable(pIpAddrtable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER)
{
free(pIpAddrtable);
cout <<"Za mała ilosc pamięci";
}

if (pIpAddrtable == NULL) {
printf("Memory allocation failed for GetIpAddrTable\n");
exit(1);
}

if (dwRetVal2 = GetIpAddrTable(pIpAddrtable, &dwSize, 0) != NO_ERROR)
{
printf("Mamy error %s", dwRetVal2);
}
}



//stop
pArpEntry->dwIndex = pIpAddrtable->table[0].dwIndex;
pArpEntry->dwPhysAddrLen = 6;
pArpEntry->bPhysAddr[0] = '0x01';
pArpEntry->bPhysAddr[1] = '0xb2';
pArpEntry->bPhysAddr[2] = '0xd3';
pArpEntry->bPhysAddr[3] = '0xd4';
pArpEntry->bPhysAddr[4] = '0x05';
pArpEntry->bPhysAddr[5] = '0x16';
pArpEntry->dwType = MIB_IPNET_TYPE_STATIC;
pArpEntry->dwAddr = ip;

if (CreateIpNetEntry(pArpEntry) == ERROR_ACCESS_DENIED)
{
cout <<"Dostęp zabroniony ";
}
while (pAdapter)
{
printf(TEXT("Nazwa adaptera: %s \n"), pAdapter->AdapterName);
printf("Adres adaptera: %s \n", pAdapter->IpAddressList.IpAddress.String);
printf("Maska: %s \n ", pAdapter->IpAddressList.IpMask.String);
printf("Opis: %s \n ", pAdapter->Description);
printf("Serwer DHCP %s \n ", pAdapter->DhcpServer.IpAddress.String);
printf("Indeks: %5d \n ", pAdapter->Index);

cout <<endl;
pAdapter = pAdapter->Next;
}




return 0;
}

最佳答案

正如我的评论所建议的那样,不要逐字记录 C示例的实现,您应该对其进行调整,使其不使用 malloc 分配原始内存, 而不是使用 std::vector .

此外,您的样本中有几个错误,主要的错误是您使用的是未初始化的 pArpEntry。指针。我稍后会解决这个问题。

这是一个正确的示例,它可以正常工作并且不使用动态内存分配。

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <windows.h>
#include <winsock2.h>
#include <ws2ipdef.h>
#include <iphlpapi.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <vector>

#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "ws2_32.lib")
using namespace std;

int main()
{
ULONG ulOutBufLen;
DWORD dwRetVal;
ulOutBufLen = 0;

// create a vector we will use for the PIP_ADAPTER_INFO data
std::vector<char> adapterInfo;

// call the INET API function with the vector contents serving
// as the PIP_ADAPTER_INFO
if (GetAdaptersInfo(reinterpret_cast<PIP_ADAPTER_INFO>(adapterInfo.data()), &ulOutBufLen) == ERROR_BUFFER_OVERFLOW)
// resize the buffer
adapterInfo.resize(ulOutBufLen);

注意最后两行代码。 GetAdaptersInfo首先调用缓冲区大小为 0 的函数。这将失败并返回 ERROR_BUFFER_OVERFLOW。错误(希望如此)。一旦它这样做了,我们就调整 adapterInfo 的大小。 vector 到 ulOutBufLen 的大小,而不是使用 malloc ,但只需调用 std::vector::resize功能。没有动态内存分配,没有指针等。

请注意,我们必须 reinterpret_cast API 调用中的指针,因为这是调用要求的指针类型。

进行中:

    if ((dwRetVal = GetAdaptersInfo(reinterpret_cast<PIP_ADAPTER_INFO>(adapterInfo.data()), &ulOutBufLen) != ERROR_SUCCESS))
{
std::cout << "GetAdaptersInfo call failed with " << dwRetVal;
return -1;
}

PIP_ADAPTER_INFO pAdapter = reinterpret_cast<PIP_ADAPTER_INFO>(adapterInfo.data());

如果在调整大小后出现错误,我们将停止程序。如果成功,我们通过将适配器信息的地址分配给 pAdapter 来简化我们的代码。通过 reinterpret_cast关于返回的适配器信息。

进行中:

    DWORD dwSize = 0;
DWORD dwRetVal2 = 0;
std::vector<char> pIpAddrtable;

if (GetIpAddrTable(reinterpret_cast<PMIB_IPADDRTABLE>(pIpAddrtable.data()), &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER)
{
pIpAddrtable.resize(dwSize);
if (dwRetVal2 = GetIpAddrTable(reinterpret_cast<PMIB_IPADDRTABLE>(pIpAddrtable.data()), &dwSize, 0) != NO_ERROR)
{
std::cout << "Many error " << dwRetVal2;
return -1;
}
}

这基本上与 PIP_ADAPTER_INFO 相同的模式以前的代码。我们创建一个 vector ,调用 IP 函数获取大小,使用返回的大小调整 vector 的大小。

进行中:

    MIB_IPNETROW arpEntry;
if (CreateIpNetEntry(&arpEntry) == ERROR_ACCESS_DENIED)
{
cout << "Access denied\n";
}

我们不需要在对 CreateIpNetEntry 的调用中分配任何东西.我们需要做的就是传递现有 MIB_IONETROW 的地址实例。这消除了您在原始代码中遇到的未初始化指针错误。

进行中:

    PMIB_IPADDRTABLE theTable = reinterpret_cast<PMIB_IPADDRTABLE>(pIpAddrtable.data());
arpEntry.dwIndex = theTable->table[0].dwIndex;
arpEntry.dwPhysAddrLen = 6;
arpEntry.bPhysAddr[0] = 0x01;
arpEntry.bPhysAddr[1] = 0xb2;
arpEntry.bPhysAddr[2] = 0xd3;
arpEntry.bPhysAddr[3] = 0xd4;
arpEntry.bPhysAddr[4] = 0x05;
arpEntry.bPhysAddr[5] = 0x16;
arpEntry.dwType = MIB_IPNET_TYPE_STATIC;
arpEntry.dwAddr = ip;

我们得到一个指向 PMIB_ADDRTABLE 的指针通过 reinterpret_cast -ing pIpAddrtable 中的数据 vector (我们称指针为 theTable )。

进行中:

    while (pAdapter)
{
std::cout << pAdapter->AdapterName << "\n";
std::cout << pAdapter->IpAddressList.IpAddress.String << "\n";
std::cout << pAdapter->IpAddressList.IpMask.String << "\n";
std::cout << pAdapter->Description << "\n";
std::cout << pAdapter->DhcpServer.IpAddress.String << "\n";
std::cout << pAdapter->Index << "\n";
std::cout << endl;
pAdapter = pAdapter->Next;
}
return 0;
}

这会输出适配器信息。

同样,为什么这有效的神奇之处在于我们使用了 std::vector<char>并在 Windows IP 函数返回给我们正确的缓冲区大小时调整 vector 的大小。这消除了 malloc 的使用, 而不是我们简单地使用 std::vector::resize .

我们需要做的另一件事是使用 reinterpret_cast ,因为 API 函数实际上需要正确的指针类型才能使代码正确编译。这很丑,但这就是C的样子接口(interface)被编码,所以C++做同样的事情需要等价物。

没有调用 malloc , 没有调用 free ,没有要处理的指针(reinterpret_cast 除外),没有内存泄漏。

下面是使用在线 Visual Studio 2015 编译器的完整实现:​​

Complete Example

关于c++ - 代码arp数组、指针和内存分配的不可理解部分(Windows IP函数),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41051269/

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