2

编辑:更改标题以忽略我的假设。

我有一个用 c 编写的库,它使用 posix 消息队列在线程之间传递指向某些运行时数据的指针。

在数据来自用户应用程序的情况下,一切似乎工作正常,并且我能够访问来自消息队列的指向结构的指针所指向的数据。

现在,我有一个特殊情况,库本身将对结构的一个实例进行 malloc,设置一个标志并将其发送到同一个队列。在接收端,结构为空,标志为零。在指针上调用 free 会导致崩溃。

这是代码:

volatile s_thestruct * volatile data = malloc(sizeof(s_thestruct));
data->flags = THE_FLAG;
mq_send(handle, (char *)&data, sizeof(s_thestruct *), 1)

在接收端:

ssize_t read = mq_receive(handle, (char*)&data, sizeof(s_thestruct*), NULL);
if(read != sizeof(s_thestruct *))
{
 // Error handling, no problems here
}
if(data->flags == THE_FLAG)
{
// Do something, never gets here
}
// Do something else, no it is not freed here

// Finally
free(data); // <--CRASH

我会得到:

*** glibc detected *** /usr/bin/applicationthingy: free(): invalid pointer: 0x08053cf0 ***

其次是转储。在内存映射转储中,我发现:

....
08048000-0804a000 r-xp 00000000 08:01 802680     /usr/bin/applicationthingy
0804a000-0804b000 r--p 00001000 08:01 802680     /usr/bin/applicationthingy
0804b000-0804c000 rw-p 00002000 08:01 802680     /usr/bin/applicationthingy
0804c000-0806f000 rw-p 00000000 00:00 0          [heap]
b6e00000-b6e21000 rw-p 00000000 00:00 0 
....

那么,有人对这里发生的事情有任何建议吗?

4

2 回答 2

4

假设它们来自相同的地址空间,那么(传递指针)应该可以正常工作。

我唯一能想到的是,队列是否有可能是从单独的进程中写入的?这将使指针变得无用,因为它们指向的内容在不同的进程中完全不同。

不过老实说,除非结构本身很大,否则我不会像那样传递指针。如果您通过该结构,您将获得能够执行正确的进程间队列的所有优势。

要检查的另一件事是该库以某种方式从与您的主代码不同的内存领域获取其分配。这将是一种会导致free失败但可能不会导致错误标志的情况,因为即使它们使用不同的竞技场,它们也会位于相同的地址空间中。

至少,您应该data在发送端和接收端打印出 的值,以确保它毫发无损。完全有可能其他一些代码可能会破坏它(la缓冲区溢出等等)。

于 2012-10-04T10:24:39.947 回答
1

您应该传递datanot &data(数据地址),在mq_send(handle, (char *)&data, sizeof(s_thestruct *), 1).

于 2012-10-04T10:26:51.773 回答