我有一个像这样分配的结构:
static struct cparray_buffer_t *_cparray;
struct __attribute__ ((__packed__)) cparray_buffer_t
{
u_int64_t buflen;
u_char buf[buffersize];
}
.
.
.
_cparray = (struct cparray_buffer_t *)calloc(1024, sizeof(struct cparray_buffer_t);
以后在程序中我尝试像这样做一个memcpy
memcpy(_cparray[0].buf, test, buffersize);
我得到一个sigsegv
我是否在memcpy中正确地引用了参考文献?
编辑:在gdb中,当实际使用数组时,似乎_cparray的地址是0x0。我试图在_cparray上放置一个数据观察点,但我没有看到任何释放它的东西。有趣的是,如果我在& _cparray上观看它仍然有一个有效的地址,但*& _cparray是0x0
edit2:不知道它是否有所作为,但是calloc在thread1中,并且segfo在thread2中发生。我的印象是,所有线程都可以看到全局静态。这是对的吗?
由于
发生了什么事?
以下是_cparray
上观察点的输出Old value = (struct cparray_buffer_t *) 0x284ba000
New value = (struct cparray_buffer_t *) 0x0
0x28102c83 in sem_init () from /lib/libc.so.7
答案 0 :(得分:0)
全局变量在所有线程中都是可见的,无论是否为静态。 static关键字只提供变量文件范围,以便它只在文件中可见。由于它只在文件中可见,因此使用该变量的代码必须位于定义它的文件中。
我看到的一个问题是人们将静态变量放入头文件中,期望变量对多个文件可见。结果是静态变量在包含头的每个文件中重复,导致静态变量的几个不同实例,这些实例之间没有共享,因为它们是不同的内存位置。
由于这是一个多线程应用程序,其中一个线程创建内存区域,另一个线程使用内存区域,因此您可能会遇到竞争条件,其中第二个线程正在访问内存区域,然后由第一个帖子。
我首先将指针初始化为例如
的已知值static struct cparray_buffer_t *_cparray = 0;
在第二个线程中,您可以测试变量是否具有检查为0的地址,如果它为零则休眠并重试,直到它变为非零,这意味着第一个线程已分配内存。一种优选的方法是第一个线程分配内存然后启动第二个线程来使用内存。或者你可以使用其他一些线程同步,只要第二个线程等到第一个线程在尝试使用指针之前分配了内存之后。
memcpy()函数调用看起来是正确的,假设test是某种类型的指针,例如数组。我假设代码看起来像:
u_char test[buffersize];
// do some things involving test
// save the things put into test
memcpy (_cparray[0].buf, test, buffersize);