错误:在此定义或声明[-Werror] |之外,在参数列表中声明的“ struct addrinfo”将不可见

时间:2018-10-04 16:50:15

标签: c gcc glibc

如果我尝试使用C标准之一进行编译,就会得到此信息:

-std=c99-std=c11-std=c17

如果我删除它们,编译效果很好,或者如果我使用-std=gnuXX也可以

为什么会这样,因为我无法修复。

program.c:

#include <string.h>
#include <stdio.h>
#include <netinet/in.h>
#include <net/if.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>
#include <unistd.h>

#define PORT "5555"
#define BACKLOG 5

int getAdr_fd(struct addrinfo server, struct addrinfo **res );
int create_fd( struct addrinfo **res );
int accept_fd( struct sockaddr_storage *their_addr, int *sockfd );
int list_fd( int *sockfd );
int bind_fd( struct addrinfo **res, int *sockfd );
ssize_t write_fd( const char *const msg, int *new_fd );

int main(void){
    const char *msg = "Hello socket World!\n";
    struct sockaddr_storage their_addr;
    struct addrinfo server, *res;
    int sockfd, new_fd;

    /* create a socket: */
    getAdr_fd( server, &res );
    sockfd = create_fd( &res );

    /* Bind */
    bind_fd( &res, &sockfd );

    /* Listen */
    list_fd( &sockfd );

    /* Accept connection: */
    new_fd = accept_fd( &their_addr, &sockfd );

    /* Write */
    write_fd( msg, &new_fd );

    /* close: */
    close(sockfd);
    freeaddrinfo(res);
 }

 int getAdr_fd(struct addrinfo server, struct addrinfo **res ){
    int getfd;

    /* Create address structs with getaddrinfo(): */

    memset(&server, 0, sizeof server);
    server.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever
    server.ai_socktype = SOCK_STREAM;
    server.ai_flags = AI_PASSIVE; // fill in my IP for me

    getfd = getaddrinfo( NULL, PORT, &server, res);
    if (getfd != 0) {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror( getfd ));
        exit(EXIT_FAILURE);
    }else{
        printf("getaddrinfo() \tOK\n");
        return getfd;
    }
}

int create_fd( struct addrinfo **res ){
    int sockfd = socket((*res)->ai_family, (*res)->ai_socktype, (*res)->ai_protocol);
    if (sockfd == -1 ){
        printf("Error, socket()\n");
        exit ( EXIT_FAILURE );
    }else{
        printf("socket() \tOK\n");
        return sockfd;
    }
}

int bind_fd( struct addrinfo **res, int *sockfd ){
    int bindfd = bind(*sockfd, (*res)->ai_addr, (*res)->ai_addrlen);
    if (bindfd == -1 ){
        printf("Error, bind(), check line 34\n");
        exit ( EXIT_FAILURE );
    }else{
        printf("bind() \t\tOK\n");
        return bindfd;
    }
}

int accept_fd(  struct sockaddr_storage *their_addr, int *sockfd  ){
    int new_fd;
    socklen_t addr_size = sizeof( *their_addr );
    new_fd = accept(*sockfd, (struct sockaddr *)their_addr, &addr_size);
    if (new_fd == -1 ){
        printf("Error, accept()\n");
        exit ( EXIT_FAILURE );
    }else{
        printf("accept() \tOK\n");
        return new_fd;
    }
}

int list_fd( int *sockfd ){
    int listfd = listen(*sockfd, BACKLOG);
    if (listfd == -1 ){
        printf("Error, listen()\n");
        exit ( EXIT_FAILURE );
    }else{
        printf("listen() \tOK\n");
        return listfd;
    }
}

ssize_t write_fd( const char *const msg, int *new_fd ){
    size_t len = strlen(msg);
    ssize_t wrtfd;
    wrtfd = write(*new_fd, msg, len );
    if (wrtfd == -1 ){
        printf("Error, write()\n");
        exit ( EXIT_FAILURE );
    }else{
        printf("write() \tOK\n");
    }

    return wrtfd;
}

编译器标志:

-Wpedantic -Wall -Wextra -Werror -std=c17 -Wstrict-prototypes  -Wmissing-prototypes -Wmisleading-indentation -Wduplicated-cond -Wold-style-definition -Wconversion -Wshadow -Winit-self -Wfloat-equal -Wwrite-strings -Wcast-align=strict -Wformat -O0 -g

输出:

program.c:14:22: error: ‘struct addrinfo’ declared inside parameter list will not be visible outside of this definition or declaration [-Werror]
 int getAdr_fd(struct addrinfo server, struct addrinfo **res );
                      ^~~~~~~~
program.c:15:23: error: ‘struct addrinfo’ declared inside parameter list will not be visible outside of this definition or declaration [-Werror]
 int create_fd( struct addrinfo **res );
                       ^~~~~~~~
program.c:18:21: error: ‘struct addrinfo’ declared inside parameter list will not be visible outside of this definition or declaration [-Werror]
 int bind_fd( struct addrinfo **res, int *sockfd );
                     ^~~~~~~~
program.c: In function ‘main’:
program.c:24:21: error: storage size of ‘server’ isn’t known
     struct addrinfo server, *res;
                     ^~~~~~
program.c:28:16: error: type of formal parameter 1 is incomplete
     getAdr_fd( server, &res );
                ^~~~~~
program.c:28:24: error: passing argument 2 of ‘getAdr_fd’ from incompatible pointer type [-Werror=incompatible-pointer-types]
     getAdr_fd( server, &res );
                        ^~~~
program.c:14:57: note: expected ‘struct addrinfo **’ but argument is of type ‘struct addrinfo **’
 int getAdr_fd(struct addrinfo server, struct addrinfo **res );
                                       ~~~~~~~~~~~~~~~~~~^~~
program.c:29:25: error: passing argument 1 of ‘create_fd’ from incompatible pointer type [-Werror=incompatible-pointer-types]
     sockfd = create_fd( &res );
                         ^~~~
program.c:15:34: note: expected ‘struct addrinfo **’ but argument is of type ‘struct addrinfo **’
 int create_fd( struct addrinfo **res );
                ~~~~~~~~~~~~~~~~~~^~~
program.c:32:14: error: passing argument 1 of ‘bind_fd’ from incompatible pointer type [-Werror=incompatible-pointer-types]
     bind_fd( &res, &sockfd );
              ^~~~
program.c:18:32: note: expected ‘struct addrinfo **’ but argument is of type ‘struct addrinfo **’
 int bind_fd( struct addrinfo **res, int *sockfd );
              ~~~~~~~~~~~~~~~~~~^~~
program.c:45:5: error: implicit declaration of function ‘freeaddrinfo’ [-Werror=implicit-function-declaration]
     freeaddrinfo(res);
     ^~~~~~~~~~~~
program.c:24:21: error: unused variable ‘server’ [-Werror=unused-variable]
     struct addrinfo server, *res;
                     ^~~~~~
program.c: At top level:
program.c:48:23: error: ‘struct addrinfo’ declared inside parameter list will not be visible outside of this definition or declaration [-Werror]
  int getAdr_fd(struct addrinfo server, struct addrinfo **res ){
                       ^~~~~~~~
program.c:48:32: error: parameter 1 (‘server’) has incomplete type
  int getAdr_fd(struct addrinfo server, struct addrinfo **res ){
                ~~~~~~~~~~~~~~~~^~~~~~
program.c: In function ‘getAdr_fd’:
program.c:56:23: error: ‘AI_PASSIVE’ undeclared (first use in this function); did you mean ‘AF_WANPIPE’?
     server.ai_flags = AI_PASSIVE; // fill in my IP for me
                       ^~~~~~~~~~
                       AF_WANPIPE
program.c:56:23: note: each undeclared identifier is reported only once for each function it appears in
program.c:58:13: error: implicit declaration of function ‘getaddrinfo’; did you mean ‘getAdr_fd’? [-Werror=implicit-function-declaration]
     getfd = getaddrinfo( NULL, PORT, &server, res);
             ^~~~~~~~~~~
             getAdr_fd
program.c:60:46: error: implicit declaration of function ‘gai_strerror’; did you mean ‘strerror’? [-Werror=implicit-function-declaration]
         fprintf(stderr, "getaddrinfo: %s\n", gai_strerror( getfd ));
                                              ^~~~~~~~~~~~
                                              strerror
program.c:60:40: error: format ‘%s’ expects argument of type ‘char *’, but argument 3 has type ‘int’ [-Werror=format=]
         fprintf(stderr, "getaddrinfo: %s\n", gai_strerror( getfd ));
                                       ~^     ~~~~~~~~~~~~~~~~~~~~~
                                       %d
program.c:48:32: error: unused parameter ‘server’ [-Werror=unused-parameter]
  int getAdr_fd(struct addrinfo server, struct addrinfo **res ){
                ~~~~~~~~~~~~~~~~^~~~~~
program.c: At top level:
program.c:68:23: error: ‘struct addrinfo’ declared inside parameter list will not be visible outside of this definition or declaration [-Werror]
 int create_fd( struct addrinfo **res ){
                       ^~~~~~~~
program.c:68:5: error: conflicting types for ‘create_fd’
 int create_fd( struct addrinfo **res ){
     ^~~~~~~~~
program.c:15:5: note: previous declaration of ‘create_fd’ was here
 int create_fd( struct addrinfo **res );
     ^~~~~~~~~
program.c: In function ‘create_fd’:
program.c:69:31: error: dereferencing pointer to incomplete type ‘struct addrinfo’
     int sockfd = socket((*res)->ai_family, (*res)->ai_socktype, (*res)->ai_protocol);
                               ^~
program.c: At top level:
program.c:79:21: error: ‘struct addrinfo’ declared inside parameter list will not be visible outside of this definition or declaration [-Werror]
 int bind_fd( struct addrinfo **res, int *sockfd ){
                     ^~~~~~~~
program.c:79:5: error: conflicting types for ‘bind_fd’
 int bind_fd( struct addrinfo **res, int *sockfd ){
     ^~~~~~~
program.c:18:5: note: previous declaration of ‘bind_fd’ was here
 int bind_fd( struct addrinfo **res, int *sockfd );
     ^~~~~~~
program.c: In function ‘bind_fd’:
program.c:80:38: error: dereferencing pointer to incomplete type ‘struct addrinfo’
     int bindfd = bind(*sockfd, (*res)->ai_addr, (*res)->ai_addrlen);
                                      ^~
cc1: all warnings being treated as errors

我注意到的另一个奇怪的事情是:

program.c:45:5: error: implicit declaration of function ‘freeaddrinfo’ [-Werror=implicit-function-declaration]
 freeaddrinfo(res);

但是其中包含文件:

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.

Linux Mint 19,GCC-8.0.1。

2 个答案:

答案 0 :(得分:2)

getaddrinfo函数以及扩展的struct addrinfo类型由POSIX指定。这意味着它们不属于C标准。

因此,当您指定-std=c99-std=c11-std=c17时,它将排除那些类型,因为它们不是标准指定的。指定-std=gnuxx选项包括这些类型的定义。

答案 1 :(得分:1)

这与glibc错误接壤。尽管struct addrinfo确实是C标准的一部分,但<netdb.h>也不是C标准的一部分,所以在该标头中定义它(对非常旧的POSIX版本而言)不会有任何危害。

如果使用-D_GNU_SOURCE进行编译,您仍然可以指定任何C标准选项并获得GNU扩展。请参阅glibc文档和手册页: