在hostent结构上设置指针时出现意外结果

时间:2011-08-09 00:14:18

标签: c++ pointers memory-management

我确信这是由于一个愚蠢的错误,但我在几个小时内一直在调整,我无法解决问题。

在我的程序中,我有一个函数返回给定域的地址。它调用getaddrinfo,将地址复制到新的dinamically asigned变量,将其指针设置为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的不同值。在将指针设置为hostent结构后,它看起来addr的值发生了变化。

1 个答案:

答案 0 :(得分:3)

来自MSDN上的hostent结构

  

h_addr_list 以NULL结尾的主机地址列表。   地址以网络字节顺序返回。宏 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;

现在,我相信你看到了问题。 :)

<强> [更新]

设置它的正确方法实际上是简单而自动的。您应该致电gethostbyaddrgethostbyname,他们会返回指向hostent的指针。这在MSDN中得到了很好的解释。如果您想手动设置hostent,我不建议,您必须创建一个指向addr.s_addr的指针数组,并将h_addr_list设置为数组。该数组应包含最后一个null元素。我没有看到任何你想要手动操作的原因,因为操作系统会为你做这件事。