// compile with: g++ 1.cc -o test -Wall `pkg-config --cflags --libs glib-2.0` -lgthread-2.0
// or g++ 1.cc -o testq -lglib-2.0 -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include/ -lgthread-2.0c
#include <glib.h>
#include <iostream>
#include <string.h>
int counter;
GAsyncQueue *q;
typedef struct MyStruct {
int foo;
char *data;
} *MyStructPtr;
gpointer looper(gpointer data) {
g_thread_init(NULL);
while (1) {
while (g_async_queue_length(q) > 0) {
MyStructPtr xtransport;
xtransport = new struct MyStruct;
xtransport = (MyStructPtr)g_async_queue_try_pop(q);
// The actual code is acting as weird, as if we have here, xtransport->data = last_text_value_ever_received;
std::cout << "str # " << xtransport->foo << ":" << xtransport->data << ":str\n";
}
}
}
void adder(char *data) {
char *processedData;
// someExternalAPICallToprocessData(data, &processeddata);
processedData = (char *)data;
MyStructPtr dtransport;
dtransport = new struct MyStruct;
dtransport->data = processedData;//processeddata;
dtransport->foo = ++counter;
g_async_queue_push(q, (gpointer*) dtransport);
}
int main() {
GThread *l;
g_thread_init(NULL);
q = g_async_queue_new();
l = g_thread_create(looper, NULL, FALSE, NULL);
sleep(2);
char *t;
t = strdupa("1111");
adder(t);
t = strdupa("222");
adder(t);
sleep (5);
}
这是一个更大项目的实验室模型。在项目中,会注意到一种奇怪的行为;
而不是main(),我们坐在回调函数中,它从系统组件获取一些数据。尝试在放入队列之前打印(例如cout)这些数据,可能会得到如下结果:
N1(回拨):aaaabbbbccc
N2(回拨中):bbbbaaaacccc。
同样,如果对(新设置的指针)dttransport->数据的访问是在创建该数据的同一代码(mainloop/callback函数)中进行的,那就没问题了。
但无法获得队列中第一个元素的正确值!数据字段总是一样的——通过队列访问收集到的数据,只能得到上次回调时设置的值;邪恶的指针该死!
街道1:bbbbaaaacccc。
街道2:bbbbaaaacccc。
回调函数定义为:
int someExternalAPICallToprocessData(...., unsigned char ** data);
它返回数据的长度,并且**-返回指向指针的指针?所以这就是解决问题。
问题是,
会不会
someExternalAPICallTOprocessData()使用指向固定地址的指针填充&processeddata,该地址只存储上一次调用的数据
?
如何将char*的副本返回并安全地放入MyStruct?注意,下一个函数使用偏移量。。。
process(dequeued->data);
void process(char *data) {
my *ptr = NULL;
ptr = data + SOME_SIZE_CONST
...
}
不知何故,memcpy'ng的processedData内容似乎分割了.so库,其中包含一些externalapicalltoprocessdata()。在模拟上下文中,它是adder()的结尾;在实际上下文中,它是内核网络的回调函数的结尾;非常有趣。