0

I have a structure allocated like so:

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);

and later on in the program I try to do a memcpy like so

memcpy(_cparray[0].buf, test, buffersize);

and I get a sigsegv

Am I making the reference correctly in the memcpy?

edit: in gdb, it seems like the address for _cparray is 0x0 when it comes time to actually use the array. I tried to put a data watchpoint on _cparray and I don't see anything freeing it. Interestingly enough, if I put a watching on &_cparray it still has a valid address, but *&_cparray is 0x0

edit2: Don't know if it makes a difference, but the calloc is in thread1, and the segfault is happening in thread2. I was under the impression global statics are visible to all threads though. is this correct?

Thanks

What is going on?

Here is the output from the watchpoint on _cparray

Old value = (struct cparray_buffer_t *) 0x284ba000
New value = (struct cparray_buffer_t *) 0x0
0x28102c83 in sem_init () from /lib/libc.so.7
Derek
  • 11,715
  • 32
  • 127
  • 228
  • just make sure that `_cparray[0].buf` and `test` are allocated, and both larger than `buffersize` and it should work – Sam I am says Reinstate Monica Aug 08 '12 at 19:46
  • So, `calloc()` is returning 0x0? Or is `_cparray` somehow getting overwritten later? – twalberg Aug 08 '12 at 19:53
  • in your debugger is `_cparray` allocated on the line after you believe that you allocate it? – Sam I am says Reinstate Monica Aug 08 '12 at 19:55
  • _cparray is being overwritten later I guess, because right after calloc, _cparray is allocated. I apparently can't figure out where the _cparray is being overwritten or free'd – Derek Aug 08 '12 at 19:57
  • just remembered that this is happening across 2 threads -added an edit for that in case it makes a difference – Derek Aug 08 '12 at 20:05
  • Are the multithreaded accesses happening at about the same time? Or is one happening way later than the other? What architecture are you running on (x86, x86-64, ARM, other)? – Adam Rosenfield Aug 08 '12 at 20:08
  • x86-64, FreeBSD. The accesses are not happening at the same time...there is only one thread actually accessing it..it is just initialized in the first thread – Derek Aug 08 '12 at 20:09
  • weird. I am using sem_init to initialize my sem_t variables. When I moved the initialization of the array to AFTER the semaphores were created, it didn't clear the variable. – Derek Aug 08 '12 at 20:30
  • 1
    Have you tried using Valgrind to see if you have some sort of memory stomping happening somewhere else unrelated? Have you tried setting a data [watchpoint](http://www.delorie.com/gnu/docs/gdb/gdb_30.html)? – Adam Rosenfield Aug 08 '12 at 20:41
  • I set a data watchpoint on cparray and I got the following. So as I confirmed earlier, it seems like when I call sem_init, my variables are getting reset. – Derek Aug 13 '12 at 18:36

1 Answers1

0

Global variables are visible from all threads whether static or not. The static keyword just gives the variable file scope so that it is only visible within the file. Since it is only visible within the file, the code using the variable must be in the file where it is defined.

One problem that I have seen is where people put a static variable into a header file expecting the variable to be visible to more than one file. The result is that the static variable is duplicated in each file the header is included resulting in several different instances of the static variable none of which are shared between the various files because they are different memory locations.

Since this is a multi-threaded application with one thread creating the memory area and a second thread using the memory area, you may have a race condition in which the second thread is accessing the memory area before it has been allocated by the first thread.

I would first of all initialize the pointer to a known value for instance

static struct cparray_buffer_t *_cparray = 0;

In the second thread you can then test whether the variable has an address with a check against 0 and if it is zero then sleep and retry until it becomes nonzero meaning that the first thread has allocated the memory. A preferred approach would be for the first thread to allocate the memory and then start the second thread to use the memory. Or you may use some other thread synchronization so long as the second thread waits until the first thread has allocated the memory before it tries to use the pointer.

The memcpy() function call looks correct assuming that test is a pointer of some kind such as an array. I assume that the code would look something like:

u_char test[buffersize];
// do some things involving test

// save the things put into test
memcpy (_cparray[0].buf, test, buffersize);
Richard Chambers
  • 16,643
  • 4
  • 81
  • 106