编辑:更改标题以忽略我的假设。
我有一个用c编写的库,它使用posix消息队列来传递指向线程之间某些运行时数据的指针。
如果数据来自用户应用程序,一切似乎都能正常工作,并且我能够访问指向结构的指针所指向的数据,这些数据来自消息队列。
现在,我有一个特殊情况,其中库本身将执行结构的一个实例的malloc,设置标志并将其发送到同一队列。在接收端,结构为空,标志为零。在指针上自由调用会导致崩溃。
这是代码:
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
....
那么,有人对这里发生的事情有任何建议吗?
答案 0 :(得分:4)
那个(传递指针)应该可以正常工作,假设它们来自同一个地址空间。
我唯一能想到的是,是否有可能从单独的进程中编写队列?这会使指针变得毫无用处,因为它们指向的东西在不同的过程中完全不同。
老实说,除非结构本身很大,否则我不会像那样传递指针。如果您通过该结构,您将获得能够执行适当的进程间队列的所有优势。
要检查的另一件事是库以某种方式从不同的内存领域获得其分配而不是主代码。这将导致free
失败,但可能不是错误的标志,因为即使他们使用不同的竞技场,他们也会在同一个地址空间。
至少,您应该在发送方和接收方打印出data
的值,以确保它没有受到损害。一些其他代码完全有可能破坏它(缓冲区溢出等等)。
答案 1 :(得分:1)
您应该在data
中传递&data
而非mq_send(handle, (char *)&data, sizeof(s_thestruct *), 1)
(数据地址)。