我是软件工程专业的三年级大学生,参加过操作系统课程。
我一直在使用pthreads和套接字在C中使用客户端 - 服务器聊天应用程序。我一直在尝试使用pthread来提升客户端处理的并发性,而不会产生分叉的开销。 (如果重要的话,我正在开发Ubuntu 11.04 x86)。
我没有将所有内容存储为静态或全局/局部变量,而是创建了两种结构化数据类型serverInfo_t
和clientInfo_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));
是的,修好了。我为浪费时间而道歉,但感谢大家的帮助。