Ошибка сегментации в getaddrinfo () - PullRequest
1 голос
/ 19 октября 2011

Я получаю ошибку сегментации в getaddrinfo ().

Это трассировка стека.

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb7ff4b70 (LWP 26872)]
__res_vinit (statp=0xb7ff4df4, preinit=0) at res_init.c:176
176 res_init.c: No such file or directory.
    in res_init.c
(gdb) bt
#0  __res_vinit (statp=0xb7ff4df4, preinit=0) at res_init.c:176
#1  0x0042fe95 in *__GI___res_ninit (statp=0xb7ff4df4) at res_init.c:142
#2  0x00430ea0 in *__GI___res_maybe_init (resp=0xb7ff4df4, preinit=0) at res_libc.c:122
#3  0x003f86f4 in gaih_inet (name=<value optimized out>, service=<value optimized out>, req=0xb7ff3df8, pai=0xb7ff3db4, naddrs=0xb7ff3da4)
    at ../sysdeps/posix/getaddrinfo.c:690
#4  0x003faa65 in *__GI_getaddrinfo (name=0x8203a68 "api.shoutcast.com", service=0x810ae72 "http", hints=0xb7ff3df8, pai=0xb7ff3e24)
    at ../sysdeps/posix/getaddrinfo.c:2160
#5  0x08050a87 in test_addrinfo () at /kkkk/myaddrinfo.c:33

Источник функции test_addrinfo ();

    #ifndef   NI_MAXHOST
    #define   NI_MAXHOST 1025
    #endif

    struct  addrinfo hints =
    {
        .ai_flags       = 0,        /* Input flags.                 nothing special */
        .ai_family      = PF_UNSPEC,/* Protocol family for socket.  any  */
        .ai_socktype    = SOCK_STREAM,        /* Socket type.                 take any (SOCK_RAW, SOCK_STREAM,  SOCK_DGRAM) */
        .ai_protocol    = IPPROTO_TCP,        /* Protocol for socket.         take any (IPPROTO_TCP and IPPROTO_UDP) */
        .ai_addrlen     = 0,        /* Length of socket address.    always 0 */
        .ai_addr        = NULL,     /* Socket address for socket.   always NULL */
        .ai_canonname   = NULL,     /* Canonical name for service.  always NULL */
        .ai_next        = NULL,     /* Pointer to next in list.     always NULL */
    };



    int test_addrinfo(void)
    {
        struct addrinfo *result = NULL;
        struct addrinfo *res;
        int error;

        /* resolve the domain name into a list of addresses */
        error = getaddrinfo("api.shoutcast.com", "http", &hints, &result);
        if (error != 0)
        {
            fprintf(stderr, "error in getaddrinfo: %s\n", gai_strerror(error));
            return EXIT_FAILURE;
        }

        /* loop over all returned results and do inverse lookup */
        for (res = result; res != NULL; res = res->ai_next)
        {
            char hostname[NI_MAXHOST] = "";

            error = getnameinfo(res->ai_addr, res->ai_addrlen, hostname, NI_MAXHOST, NULL, 0, 0); 
            if (error != 0)
            {
                fprintf(stderr, "error in getnameinfo: %s\n", gai_strerror(error));
                continue;
            }
            if (*hostname != '\0')
                printf("hostname: %s\n", hostname);
        }

        freeaddrinfo(result);
        return EXIT_SUCCESS;
    }

После запуска в valgrind я получил следующий журнал

    ==00:00:00:07.590 7788==
    ==00:00:00:07.590 7788== Process terminating with default action of signal 11 (SIGSEGV)
    ==00:00:00:07.590 7788==  Bad permissions for mapped region at address 0x4033BDC
    ==00:00:00:07.590 7788==    at 0x4348C8A: __res_vinit (res_init.c:176)
    ==00:00:00:07.645 7788==

Эта функция test_addrinfo) вызывается верхним слоем в моем приложении.Я протестировал ту же функцию в другом приложении, которое имеет только один main ().Это работало в этом приложении.

Я подозреваю, что я не использую правильную библиотеку gnulib или неправильные флаги компиляции.Есть подсказки или подсказки?

1 Ответ

2 голосов
/ 20 октября 2011

Я нашел проблему.Произошло переполнение стека, так как функция getaddrinfo () использует alloca () - которая распределяет память динамически, но в стеке (а не в куче).Это очень опасная функция.

Я пытался установить флаг -fstack-protector-all gcc, но это было напрасно.

...