线程C客户端 - 服务器聊天应用程序中SIGSEGV的未知原因

时间:2011-11-08 21:36:36

标签: c sockets gdb pthreads client-server

我是软件工程专业的三年级大学生,参加过操作系统课程。

我一直在使用pthreads和套接字在C中使用客户端 - 服务器聊天应用程序。我一直在尝试使用pthread来提升客户端处理的并发性,而不会产生分叉的开销。 (如果重要的话,我正在开发Ubuntu 11.04 x86)。

我没有将所有内容存储为静态或全局/局部变量,而是创建了两种结构化数据类型serverInfo_tclientInfo_t,它们存储互斥锁,文件描述符,连接标志等。这样的信息。客户端列表实现为存储在serverInfo_t中的简单单链表,在修改期间锁定和解锁。

启动服务器应用程序时,我首先调用createServer(),它建立服务器,并最终启动一个子线程,其职责是监听新连接。此函数返回指向新分配的serverInfo_t实例的指针,然后将其传递给createClient(serverInfo_t* pServer, int out_fd)的调用以创建“admin”客户端,从而允许服务器本身用作客户端。这是我遇到问题的地方,因为它一旦调用createClient()就会产生段错误。 (一些修剪过的代码如下:)

int main(int argc, char** argv)
{
    // ...
    // Get listenPort from argv[1].

    // Initialize the server.
    serverInfo_t* pServer = createServer(listenPort);

    // If createServer() failed, exit.
    if (!pServer) {
        fatal_error("ERROR: Unable to create server!"); // exit program
    }

    // Create and register the admin client.
    clientInfo_t* pAdmin = createClient(pServer, STDOUT_FILENO); // Outputs directly to stdout

    // ...
}

在使用gdb调试程序时,我正在浏览main()并注意到一些有趣的输出:

(gdb) n
22      serverInfo_t* pServer = createServer(listenPort);
(gdb) n
[New Thread 0xb7e53b70 (LWP 7986)]
25      if (!pServer) {
(gdb) n
30      clientInfo_t* pAdmin = createClient(pServer, FD_STDOUT);
(gdb) n
server4: malloc.c:3096: sYSMALLOc: Assertion `(old_top == (((mbinptr) (((char *)
&((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) &&
old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof
(struct malloc_chunk, fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & ~((2 *
(sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long)old_end &
pagemask) == 0)' failed.

Program received signal SIGABRT, Aborted.
0xb7fe1424 in __kernel_vsyscall ()
(gdb) n
Single stepping until exit from function __kernel_vsyscall,
which has no line number information.
[Thread 0xb7e53b70 (LWP 7986) exited]

Program terminated with signal SIGABRT, Aborted.
The program no longer exists.
(gdb)

这里发生了什么?它看起来好像程序完全跳过了对createServer()的调用,即使NULL检查已通过。 GDB是否拒绝进入createServer()函数,还是由于某些编译器优化问题而被简单地绕过?如果是这种情况,那么[New Thread 0xb7e53b70 (LWP 7986)]输出是什么?究竟是什么导致malloc.c中的断言失败?

如果您能提供此问题,我将不胜感激。如果我的方法或我提供的信息有问题,请告诉我。如果有必要,我愿意发布我的完整Makefile和源代码,但是运行makefile需要进行一些修改(即更改Makefile的$(OUTDIR)变量)。

编辑:我认为我找到了问题的原因。

createClient()

// ...
clientInfo_t* client = (clientInfo_t*)malloc(sizeof(clientInfo_t*)); // Accidental typo.

修正:

// ...
clientInfo_t* client = (clientInfo_t*)malloc(sizeof(clientInfo_t)); 
是的,修好了。我为浪费时间而道歉,但感谢大家的帮助。

2 个答案:

答案 0 :(得分:5)

这看起来像是内存错误。尝试通过valgrind运行它:valgind --tool=memcheck [COMMAND]

有关详细信息,请转到Valgrind网站。

答案 1 :(得分:4)

  

这里发生了什么?

此:

malloc.c:3096: sYSMALLOc: Assertion `(old_top == (((mbinptr) ...

是堆损坏的经典签名(double free(),写入malloc() ed block的结尾等。)

用于在Linux上查找此类错误的工具是Valgrind。经常使用它,它将为您节省大量的调试时间。