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);struct in_addra の最初の 4 バイトをの 50 バイト バッファの先頭にコピーしmainます。このページで提案されているようsizeof(struct in_addr)に、システム上で実際には 4 バイトであると仮定します。そうでない場合、コードはさらに悪化します。一般に、式を使用してコピーする量を計算する必要があります。sizeof

次に、OK を渡しstruct in_addrますinet_ntoa。あなたの関数では、.を含むバッファへのポインタ&pLocalHostAddressのアドレスです。したがって、構造体を取得するために 2 回逆参照します。struct in_addr

しかしmain、は、を含むバッファ&pLocalHostAddressのアドレスです。したがって、一度だけ逆参照する必要があります。代わりに、コードはインターネット アドレスをポインターのバイトとして解釈しようとするため、そのポインターを逆参照するとセグメンテーション エラーが発生します。struct in_addr

のコードをに変更すると、おそらくコードが機能するように見えますが、実際にそのようなコードを使い続けるのはお勧めできません。maininet_ntoa(*(struct in_addr *)&pLocalHostAddress)

于 2015-09-11T07:54:07.580 に答える
0

MM が「コード内に pLocalHostAddress という名前の 2 つの異なる変数がある」と言ったように、二重参照解除が問題でした。次のプログラムが動作しています:

#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 に答える