2

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()が1つしかない別のアプリケーションで同じ関数をテストしました。そのアプリケーションで動作しました。

正しいgnulibライブラリまたは間違ったコンパイルフラグを使用していないのではないかと疑っています。手がかりやヒントはありますか?

4

2 に答える 2

3

問題を見つけました。関数getaddrinfo()がalloca()を使用するため、スタックオーバーフローが発生しました。これは、メモリを動的に割り当てますが、スタック上(ヒープ上ではない)に割り当てます。これは非常に危険な機能です。

-fstack-protector-all gccフラグを付けてみましたが、無駄でした。

于 2011-10-20T13:07:57.007 に答える
0

2022-02-08 16:55:33、同じ問題私はそれを解決する方法がわかりません

私は知っていました、呼び出し時にエラーがスローされますgetaddrinfo()

私のエラー情報

(gdb) run
Starting program: /document/c_cpp_program/cpp_spider/main.out
test print 000
test print 111

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7cfe813 in __GI_getaddrinfo (name=<optimized out>, service=<optimized out>, hints=<optimized out>, pai=<optimized out>)
    at ../sysdeps/posix/getaddrinfo.c:2501
2501    ../sysdeps/posix/getaddrinfo.c: No such file or directory.
(gdb) bt
#0  0x00007ffff7cfe813 in __GI_getaddrinfo (name=<optimized out>, service=<optimized out>, hints=<optimized out>, pai=<optimized out>)
    at ../sysdeps/posix/getaddrinfo.c:2501
#1  0x0000555555555367 in test_socket_api () at main.cpp:29
#2  0x00005555555554c7 in main () at main.cpp:47
(gdb)

私のエラーコードは

#include <iostream>
#include <sys/socket.h>
#include <stdio.h>
#include <netdb.h>
#include <string.h>
#include "net_opt/net_utils.h"
#include "example/other_test.h"

void test_socket_api() {
    std::string host_name = "www.google.com";
    std::string host_service = "80";
    struct addrinfo host_addr_info_limit ;
    struct addrinfo **host_addr_info_result;  //need fix ①

    std::cout << "test print 000 " << "\n" ;
    memset(&host_addr_info_limit, 0, sizeof(host_addr_info_limit));
    host_addr_info_limit = {
      .ai_flags = 0 ,
      .ai_family = AF_UNSPEC ,
      .ai_socktype = SOCK_STREAM ,
      .ai_protocol = 0 ,
      .ai_addrlen = 0 ,
      .ai_addr = NULL ,
      .ai_canonname = NULL ,
      .ai_next = NULL ,
    };
    std::cout << "test print 111" << "\n" ;

    int result_code = getaddrinfo(host_name.c_str(),
                                  host_service.c_str(),
                                  &host_addr_info_limit,
                                  host_addr_info_result);//need fix ②

    std::cout << "test print 222" << "\n" ;

    std::cout << "result_code = " << result_code << "\n";

    if (0 == result_code) {
        std::cout << "get data success ✅  \n";
    } else {
        std::cout << "get data failed ❌  :&quot; << gai_strerror(result_code) << "\n";
    }
}


int main() {
    test_socket_api();

    return 0;
}


編集1:問題を解決する方法はわかっていますが、理由はわかりません。

私の参照コード:

  1. 男getaddrinfo
  2. https://gist.github.com/jirihnidek/bf7a2363e480491da72301b228b35d5d
  3. getaddrinfo()のセグメンテーション違反

私のコードをベースにして、2つのポイントを修正します:

ポイント1:

//struct addrinfo **host_addr_info_result;     
//fix to ---> 
struct addrinfo *host_addr_info_result;

ポイント2:

//int result_code = getaddrinfo(host_name.c_str(),
//                              host_service.c_str(),
//                              &host_addr_info_limit,
//                              host_addr_info_result);
// fix to --> 
int result_code = getaddrinfo(host_name.c_str(),
                                  host_service.c_str(),
                                  &host_addr_info_limit,
                                  &host_addr_info_result);

今、私の新しい質問は次のとおりです。2つのスペルの違いはわかりません。

2022-02-09 11:58:00; 他の情報を入手しましたが、エラーの説明方法がわかりません。

情報は:

  1. struct addrinfo **host_addr_info_result;make host_addr_info_resultis 、NULLパラメータは実行エラーNULLにつながります。getaddrinfo()

  2. struct addrinfo *host_addr_info_result;makehost_addr_info_resultはですがNULL、そうで&host_addr_info_resultはありませんNULL。nullでない値はgetaddrinfo()実行を成功させます。


編集2、私はファイルを検索し/sysdeps/posix/getaddrinfo.c、メソッドの実装を確認しようとしますgetAddrinfo()

コードは次のとおりです:https ://code.woboq.org/userspace/glibc/sysdeps/posix/getaddrinfo.c.html

//file path : https://code.woboq.org/userspace/glibc/sysdeps/posix/getaddrinfo.c.html 

int
getaddrinfo (const char *name, const char *service,
             const struct addrinfo *hints, struct addrinfo **pai)
{
   .....//other code

   if (p)
    {
      *pai = p;    //this is crash point 
                   //pai is NULL is that creash reason 
      return 0;
    }

   .....//other code
}

さて、私の質問は次のとおりです:私のエラーメッセージコンテンツ/sysdeps/posix/getaddrinfo.c: No such file or directory.; コンピューターでこれらのコードを見つけるにはどうすればよいですか?

于 2022-02-08T09:14:39.633 に答える