Неожиданный результат при установке указателей на структуру hostent - PullRequest
1 голос
/ 09 августа 2011

Я уверен, что это из-за глупой ошибки, но я часами отлаживал и не мог решить проблему.

В моей программе есть функция, которая возвращает адресданный домен.Он вызывает getaddrinfo, копирует адрес в новую динамически присваиваемую переменную, устанавливает его указатель в структуру hostent и возвращает его.Тем не менее, возвращенный адрес был неверным.После некоторой отладки я понял, что его значение неожиданно меняется в некоторой точке кода.

Я сделал пример программы с соответствующей частью в этом выпуске:

#include <iostream>
#include <string.h>
#include <string>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <stdlib.h>

using namespace std;
typedef unsigned long int longip_t;

int main(int argc, char** argv) {

    struct addrinfo hints, *res;
    struct hostent *final = new hostent;

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    getaddrinfo("automation.whatismyip.com", "80", &hints, &res);

    cout << inet_ntoa(((sockaddr_in*)res->ai_addr)->sin_addr) << endl;
    in_addr *addr = new in_addr;
    memcpy((void*)addr, (void*)(&((sockaddr_in*)res->ai_addr)->sin_addr), sizeof(in_addr));
    cout << inet_ntoa(*addr) << endl;

    final->h_addr_list = (char**)addr; 
    cout << inet_ntoa(*addr) << endl;
    final->h_addr = (char*)addr; // At this point the value of addr changes
    cout << inet_ntoa(*addr) << endl;
    cout << inet_ntoa(*(in_addr*)final->h_addr_list) << endl;
    exit(0);
}

Вывод, который я получаю:

72.233.89.195
72.233.89.195
72.233.89.195
48.116.218.9
48.116.218.9

Первые три IP-адреса верны, но я получаю разные значения для последних двух IP-адресов при каждом запуске программы.Похоже, что значение addr изменяется после установки его указателя на структуру hostent.

1 Ответ

3 голосов
/ 09 августа 2011

С hostent Структура на MSDN

h_addr_list Список адресов с нулевым символом для хоста.Адреса возвращаются в сетевом порядке байтов.Макрос h_addr определен как h_addr_list [0] для совместимости со старым программным обеспечением.

final->h_addr = (char*)addr;

Таким образом, приведенная выше строка действительно является такой

final->h_addr_list[0] = (char*)addr;

Начиная с final->h_addr_list = (char**)addr;, эта строка становится такой

addr[0] = (char*)addr;

Теперь, я полагаю, вы видите проблему.:)

[Обновление]

Правильный способ установки - на самом деле просто и автоматически.Вам следует позвонить gethostbyaddr или gethostbyname, и они вернут указатель на hostent.Это хорошо объясняется в MSDN .Если вы хотите установить hostent вручную, что я не рекомендую, вам нужно создать массив указателей на addr.s_addr и установить h_addr_list на массив.Массив должен содержать последний элемент null.Я не вижу причин, почему вы хотите сделать это вручную, поскольку ОС делает это за вас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...