0

考虑以下程序:

#include <sys/socket.h> 
#include <stdio.h> 
#include <netinet/in.h>
       #include <arpa/inet.h>
       #include <string.h>
#include <netdb.h> 

void printhost(char* pLocalHostAddress )
{
   struct hostent * pHost;
   struct in_addr   **pptr;
   char hostName[128]="\0";

   gethostname(hostName, sizeof(hostName)); 
   printf("%s",hostName);
   if( NULL != (pHost = gethostbyname(hostName)) )
   {
      memcpy( pLocalHostAddress, *pHost->h_addr_list, 4);
      printf("ip address: %s\n",inet_ntoa(**(struct in_addr **)&pLocalHostAddress));
   }
}
void main()
{
   char pLocalHostAddress[50];
   printhost((char *)pLocalHostAddress);
           printf("ip address: %s\n",inet_ntoa(**(struct in_addr **)&pLocalHostAddress));

}

奇怪的是,当我尝试在函数内部打印时,它会正确打印主机 IP 地址printhost(),但是当我尝试从main()函数打印时会出现分段错误。有人可以澄清一下吗?

4

2 回答 2

1

注意:我不熟悉有问题的功能,但我的回答基于此说明此文档

将函数替换为:

struct in_addr *printhost(void)
{
// ... 
    if( NULL != (pHost = gethostbyname(hostName)) )
    {
        struct in_addr *tmp = (struct in_addr *)*pHost->h_addr_list;
        printf("ip address: %s\n",inet_ntoa(*tmp));
        return tmp;
    }
    return NULL;
}

并称之为:

struct in_addr *p = printhost();
if ( p )
    printf("ip address: %s\n",inet_ntoa(*p));

您的代码以多种方式导致未定义的行为。当触发未定义的行为时,任何事情都可能发生,包括相同的代码似乎在一个地方工作而在另一个地方不工作。深入分析这个是徒劳的,最好修复代码。

memcpy( pLocalHostAddress, *pHost->h_addr_list, 4);将 a 的前 4 个字节复制struct in_addrmain. 我将假设这sizeof(struct in_addr)实际上是本页建议的系统上的 4 个字节,否则您的代码会更糟。通常,您应该使用sizeof表达式来计算要复制多少。

然后你将它传递struct in_addrinet_ntoa可以的。在您的函数中,&pLocalHostAddress指向包含struct in_addr. 因此,您取消引用两次以获取结构。

但在 中main&pLocalHostAddress是包含的缓冲区struct in_addr的地址。所以你应该只取消引用一次。相反,您的代码尝试将 Internet 地址解释为指针的字节,当您取消引用该指针时会导致分段错误。

如果您将代码更改为 ,您的代码可能看起来可以工作,但是实际上坚持使用此类代码是一个坏主意。maininet_ntoa(*(struct in_addr *)&pLocalHostAddress)

于 2015-09-11T07:54:07.580 回答
0

我明白了,双重取消引用是问题所在,正如 MM 所说的“你的代码中有两个不同的变量,都名为 pLocalHostAddress”。以下程序正在运行:

#include <sys/socket.h> 
#include <stdio.h> 
#include <netinet/in.h>
       #include <arpa/inet.h>
       #include <string.h>
#include <netdb.h> 

void printhost(char* pLocalHostAddress )
{
   struct hostent * pHost;
   struct in_addr   **pptr;
   char hostName[128]="\0";

   gethostname(hostName, sizeof(hostName)); 
   printf("%s",hostName);
   if( NULL != (pHost = gethostbyname(hostName)) )
   {
      memcpy( pLocalHostAddress, *pHost->h_addr_list, 4);
      printf("ip address: %s\n",inet_ntoa(*(struct in_addr *)pLocalHostAddress));
   }
}
void main()
{
   char pLocalHostAddress[50];
   printhost(pLocalHostAddress);
      printf("ip address: %s\n",inet_ntoa(*(struct in_addr *)pLocalHostAddress));
}
于 2015-09-11T08:15:49.733 回答