2010-08-16 35 views
8

警告:请像对待我的菜鸟一样对待我。这是我第一个“真正的”C程序。所以如果我不明白一些事情,那就是为什么。如何在getaddrinfo中处理这个指针?

我试图按照Beej的网络编程指南中的示例制作一个聊天服务器。它被推荐,所以你去。

我想要一个函数接受指向结构的指针,修改该指针的属性,并在传递的端口上设置侦听器。在下面的代码中,我得到了一个分段错误,我真的不知道为什么。怪我是绿色的。 (在Netbeans的6.8 Ubuntu的开发,如果需要的话):

#define PORT "4400" 

typedef struct { 
    int port; 
    fd_set *connections; 
    int connections_count; 
    int listener; 
    struct addrinfo address; 
    struct addrinfo socket_hints; 
} Server; 

typedef struct { 
    struct sockaddr_storage address; // User's address 
    int fs_id;     // ID to the socket they belong to 
    char *name;     // Pointer to the user's name 
    struct User *nextUser;  // Next user in the list 
} User; 

void initialize_server(Server *passed_server, char *port) { 
    struct addrinfo *temp; 
    int result; 

    // Set up the server hints 
    memset(&passed_server->socket_hints, 0, sizeof(struct addrinfo)); 
    passed_server->socket_hints.ai_family = AF_UNSPEC; 
    passed_server->socket_hints.ai_socktype = SOCK_STREAM; 
    passed_server->socket_hints.ai_flags = AI_PASSIVE; 

    result = getaddrinfo(NULL, port, &passed_server->socket_hints, &temp); 
    printf("Result: %d\n", result); 
} 

int main(int argc, char** argv) { 
    // Set up socket stuff 
    Server *server; // Set up the server 
    memset(server, 0, sizeof(Server)); 

    fd_set read_sockets; // Master socket holder and sockets to read 
    int new_connection; // Holds the socket ID of the new connection 
    socklen_t address_length; // Used to hold the length of the address from the user 
    struct addrinfo; 

    // Useful sets 
    char buffer[1024]; 
    int bytes_recieved; 
    int yes = 1; // For SETOPT 

    // Set up server info on defined port 
    initialize_server(server, PORT); 
    FD_ZERO(&read_sockets); 

    return (EXIT_SUCCESS); 
} 

如果您需要完整的代码(我想我张贴的一切必要的),你可以在下面找到一个链接。预先感谢您的帮助或尝试!

http://pastebin.org/529545

+1

+1,为优秀的第一篇文章。欢迎来到StackOverflow。我能想到的唯一一件事可以改善这种情况:如果你通过调试器运行这段代码(比如说gdb)和调试信息,它应该告诉你这段代码是在哪个段上进行分段转换的,这可能是一个很好的起点调试。 – Thanatos 2010-08-16 03:42:24

+0

谢谢。我会窥探一下。 – Codeacula 2010-08-16 03:43:06

+1

只是一些提示。您可能想尝试在emacs 23上进行开发。另外,当您得到堆栈残余时,通常是由寻址无效内存引起的。尝试使用gdb和backtrace(bt)。它会把你带到失败的那一行。并且还可以安装valgrind,它非常适合追踪内存错误。即valgrind --leak-check = yes ./your_app。希望有所帮助。 – ant2009 2010-08-16 06:12:11

回答

6

行:

Server *server; 

实际上不分配任何空间的服务器结构,只是一个指向一个,这是设置为随机值。

它看起来像你所需要的变化是:

Server *server = malloc (sizeof (Server)); 

实际上分配一些内存供您使用。

认为区别如下:

Server *server;    | Server *server = malloc (sizeof (Server)); 
     +----------+   |   +---------+  +-----------+ 
server | ???????? | --> ??? | server | pointer | --> | structure | 
     +----------+   |   +---------+  +-----------+ 
+0

但是这样做后的呼叫不是? memset(server,0,sizeof(Server)); – Codeacula 2010-08-16 03:46:32

+1

不,这几乎肯定是导致错误的原因之一。所有'memset'都是用给定的值填充内存,你仍然必须有一个有效的可寻址内存块 - 你实际上将它传递给一个随机地址以开始填充。当我使用malloc时,我从程序中返回'Result:0'。 – paxdiablo 2010-08-16 03:48:04

+0

谢谢,绝对做到了!帮助我更多地了解指针的事情。 – Codeacula 2010-08-16 03:50:49

2
int main(int argc, char** argv) { 
// Set up socket stuff 
Server *server; // Set up the server 
memset(server, 0, sizeof(Server)); 

这是不正确。在这里,您要求memsetserver指向的内存清零。拨打memset是正确的,它不是指针server。这条线:

Server *server; 

分配内存并给你一个指针,但它不分配任何内存为指向的对象,而且它并没有给指针的初始值。因此,在这一行之后,指针只是指向内存中的某个随机点。 (它正在使用RAM中剩下的任何内容,可能)我们还没有为它分配一个有效值,所以无法将其传递给memset

现在,我们需要给它一个有效的值。你既可以:

1)分配堆栈上的Server,通过只是说:

Server server; 
memset(&server, 0, sizeof(server)); 

2)分配一个Server动态,使用malloc

Server *server = malloc(sizeof(*server)); 
// Check for NULL, which means malloc failed. 

(另外,请注意使用sizeof - 如果您更改变量的类型,则使用变量名称而不是类型将允许sizeof进行调整。)

您可能想要查找和查看关于指针的基本教程。这是第一次出现指针的人的一个非常经典的错误,所以,不要太难过。

+0

非常感谢,Thanatos。我其实刚刚在学校学到了这一点,但那里的例子已经做好了。我通过犯我自己的错误学得最好。我完全忘记了malloc。我首先通过查看其他帖子来回答头脑中的memset。如果可以的话,我会加倍努力。也非常感谢您的热烈欢迎。 – Codeacula 2010-08-16 03:54:14