2015-09-11 7 views
0

Рассмотрим следующую программу:ошибки сегментации при печати inet_ntoa функции

#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() функция. Может кто-нибудь прояснить?

+2

'** (структура in_addr **) & pLocalHostAddress)' - то, что на земле –

+0

я удалил C++ :) –

+0

Массивы затухает естественно к указателям (первый элемент), то дон Не нужно бросать массив в указатель. –

ответ

1

Примечание: Я не знаком с рассматриваемыми функциями, но основываю свой ответ на this explanation и this documentation.

Заменить функцию с:

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); копирует первые 4 байта struct in_addr в начало 50-байтового буфера в main. Я собираюсь предположить, что sizeof(struct in_addr) на самом деле 4 байта в вашей системе as suggested by this page, иначе ваш код еще хуже. В общем, вы должны использовать выражения sizeof, чтобы определить, сколько нужно скопировать.

Затем вы передаете, что struct in_addr - inet_ntoa, что в порядке. В вашей функции &pLocalHostAddress является адресом указателем на буфер, содержащий struct in_addr. Итак, вы разыгрываете два раза, чтобы получить структуру.

Но в main, &pLocalHostAddress это адрес буфер, содержащий struct in_addr. Поэтому вы должны только разыгрывать раз. Вместо этого ваш код пытается интерпретировать интернет-адрес в виде байтов указателя, вызывая ошибку сегментации при разыменовании этого указателя.

Ваш код будет, вероятно, появляется на работе если вы изменили код в main к inet_ntoa(*(struct in_addr *)&pLocalHostAddress), однако это плохая идея на самом деле сохраняются с таким кодом.

+0

спасибо за ваш ответ, это сработает, но я спрашиваю, «что является причиной того, что функция printf внутри работает нормально, но она дает ошибку сегментации, когда я пытаюсь напечатать ее в основной функции». –

+0

@pankajkushwaha обновленный –

+0

Вы правы, я не должен иметь уважение дважды в главном, его неправильное, спасибо за ваш ответ. –

0

Я получил его, двойная разыменования была проблемой, поскольку M.M сказал: «У вас есть две разные переменные в вашем коде, называемые 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)); 
}