GetAdaptersAddresses и выделение памяти

302
01 февраля 2018, 18:32

Итак имеем функцию GetAdaptersAddresses, которая возвращает список сетевых интерфейсов в системе. Описание ф-ции:

ULONG WINAPI GetAdaptersAddresses(
  _In_    ULONG                 Family,
  _In_    ULONG                 Flags,
  _In_    PVOID                 Reserved,
  _Inout_ PIP_ADAPTER_ADDRESSES AdapterAddresses,
  _Inout_ PULONG                SizePointer
);

AdapterAddresses [in, out]
A pointer to a buffer that contains a linked list of IP_ADAPTER_ADDRESSES structures on successful return.
SizePointer [in, out]
A pointer to a variable that specifies the size of the buffer pointed to by AdapterAddresses.

Согласно логике вещей, размер буфера должен быть кратен sizeof(IP_ADAPTER_ADDRESSES), однако на практике получается не так. Код:

ULONG flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER;
ULONG buffLen = 0;
IP_ADAPTER_ADDRESSES* adapters = nullptr;
ULONG ret = GetAdaptersAddresses(AF_INET, flags, NULL, NULL, &buffLen);

buffLen = 3128
sizeof(IP_ADAPTER_ADDRESSES) = 376

3128 / 376 = 8,3...

Основной вопрос: почему размер буфера не кратен размеру входящего в него элемента и как правильно выделять память под буфер с помощью new[]?

Описание функции:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa365915%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396

Answer 1

Тут надо пояснить, что выдает GetAdaptersAddresses. Она выдает не массив структур IP_ADAPTER_ADDRESSES, а наполняет переданный буфер данными, формируя однонаправленный связнный список таких структур. Помимо структур IP_ADAPTER_ADDRESSES, в этом же буффере будут данные, на которые указывают поля этой структуры, например текст с именем адаптера и т.п. Для работы следует выделить просто массив байт:

::ULONG buffLen{};
auto const retl{::GetAdaptersAddresses(AF_INET, flags, nullptr, nullptr, &buffLen)};
if(ERROR_BUFFER_OVERFLOW != retl)
{
    // обработка ошибки...
}
auto const p_buf{::std::make_unique<::std::uint8_t[]>(buffLen)};
auto const p_first{reinterpter_cast<::PIP_ADAPTER_ADDRESSES>(p_buf.get())};
auto const ret{GetAdaptersAddresses(AF_INET, flags, nullptr, p_first, &buffLen)};
if(ERROR_SUCCESS != ret)
{
    // обработка ошибки...
}
for(auto p_info{p_first}; p_info; p_info = p_info->Next)
{
    // обходим...
}
READ ALSO
Явное приведение типов в стиле Си и С++ [дубликат]

Явное приведение типов в стиле Си и С++ [дубликат]

На данный вопрос уже ответили:

264
Как добавить Interface в пакет?

Как добавить Interface в пакет?

Установил новую версию IntelliJ Idea (Community Edition 20173

286
Хранение данных в Application Android

Хранение данных в Application Android

Пишу игру под Аndroid

248
Авторизация с Selenium WebDriver через cookie

Авторизация с Selenium WebDriver через cookie

Необходимо реализовать авторизацию с Selenium WebDriver так что-бы не вводить логин и пароль для сайтов каждый раз при запускеТоесть нужно сэмитировать...

419