簡體   English   中英

C - addrinfo - 指針分割故障

[英]C - addrinfo - pointers segmentation fault

C - addrinfo - 指針分割故障

我遇到了分段錯誤; 我做了一個奇怪的修復,但我仍然擔心,因為我無法弄清楚問題是什么。 任何見解都會令人驚嘆! 在最后一個代碼塊中“修復”!

嘗試使用target_addrinfo綁定時出現分段錯誤:

struct addrinfo *my_server_res;
struct addrinfo *their_server_res;

int main(int argc, char **argv) {
//........
    set_addrinfo();
    handle_binding();
}

void set_addrinfo() {
    int status;
    struct addrinfo hints;
    struct addrinfo *target_addrinfo; // fix (1/3): **target_addrinfo
    char ipstr[INET6_ADDRSTRLEN];

    // THIS IS TRUE, takes my_server_res
    // fix(2/3): (l ? &my_server_res : &their_server_res)
    target_addrinfo = (l ? my_server_res : their_server_res); 

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE;
    char *node;
    node = (l ? "localhost" : host_name);

    // fix (3/3) 3rd argument: target_addrinfo
    if ((status = getaddrinfo(node, port, &hints, &target_addrinfo)) != 0) {
        fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
        exit(1);
    }

}

void handle_binding() {
    struct addrinfo *target_addrinfo;
    // THIS IS TRUE, takes my_server_res
    target_addrinfo = (l ? my_server_res : their_server_res);
    int b_res = bind(sockfd, target_addrinfo->ai_addr, target_addrinfo->ai_addrlen);
    if (b_res == -1) {
        perror("__Bind");
        exit(1);
    }
}

堆棧跟蹤:嘗試再次使用my_server_res時出現問題?:

Program received signal SIGSEGV, Segmentation fault.
0x0000000000401e16 in handle_binding () at ncTh.c:385
385     int b_res = bind(sockfd, target_addrinfo->ai_addr, target_addrinfo->ai_addrlen);
(gdb) backtrace
#0  0x0000000000401e16 in handle_binding () at ncTh.c:385
#1  0x0000000000401cad in setup_socket () at ncTh.c:330
#2  0x0000000000401ad0 in main (argc=6, argv=0x7fffffffdea8) at ncTh.c:266
(gdb) frame 0
#0  0x0000000000401e16 in handle_binding () at ncTh.c:385
385     int b_res = bind(sockfd, target_addrinfo->ai_addr, target_addrinfo->ai_addrlen);
(gdb) 

工作“修復”,更改為set_addrinfo():

struct addrinfo **target_addrinfo; // was *target_addrinfo
char ipstr[INET6_ADDRSTRLEN];

target_addrinfo = (l ? &my_server_res : &their_server_res); // was my_server_res : their_server_res

memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;

char *node;
node = (l ? "localhost" : host_name);
                               // 3rd argument was &target_addrinfo :
if ((status = getaddrinfo(node, port, &hints, target_addrinfo)) != 0) {
    fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
    exit(1);
}

在原始代碼中:

struct addrinfo *target_addrinfo;
target_addrinfo = (l ? my_server_res : their_server_res);

target_addrinfo指針my_server_res的值復制到target_addrinfo

getaddrinfo(node, port, &hints, &target_addrinfo)

這會將指向target_addrinfo (指向指針的指針)的指針傳遞給函數getaddrinfo ,然后通過執行等效於*&target_addrinfo = new_ptr的函數為其分配新值。 這個新值是指向getaddrinfo正在為您檢索的信息的指針。

所有這些對my_server_res沒有影響, my_server_res保留其原始值,可能為NULL。

在新代碼中:

struct addrinfo **target_addrinfo;
target_addrinfo = (l ? &my_server_res : &their_server_res);

target_addrinfo指向my_server_res的指針復制到target_addrinfo (現在是指向指針的指針)。

getaddrinfo(node, port, &hints, target_addrinfo)

這會將target_addrinfo (當前是指向my_server_res的指針)的值傳遞給函數getaddrinfo ,然后函數getaddrinfo通過執行等效的*target_addrinfo = new_ptr為其分配新值。 my_server_res現在包含一個指向getaddrinfo正在為您檢索的信息的指針。

你可能會解除對target_addrinfo問題的解除引用,我發布了這段代碼。 (晚了好然后再:))

struct addrinfo *my_server_res;
struct addrinfo *their_server_res;

struct addrinfo **target_addrinfo; //this should be global 

int main(int argc, char **argv) {
//........
    set_addrinfo();
    handle_binding();
}

void set_addrinfo() {
    int status;
    struct addrinfo hints;

    char ipstr[INET6_ADDRSTRLEN];

    // THIS IS TRUE, takes my_server_res
    target_addrinfo = (l ? &my_server_res : &their_server_res); //set it once here

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE;
    char *node;
    node = (l ? "localhost" : host_name);
    if ((status = getaddrinfo(node, port, &hints, &target_addrinfo)) != 0) {
        fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
        exit(1);
    }

}

void handle_binding() {
    //target_addrinfo should be initialized in set_addrinfo()
    int b_res = bind(sockfd, 
        (*target_addrinfo)->ai_addr,    // don't forget to dereference target_addrinfo, here
        (*target_addrinfo)->ai_addrlen); // and here

    if (b_res == -1) {
        perror("__Bind");
        exit(1);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM