json_decref() cause memory Invalid write - c

I got some problems when I call json_decref()
#include <jansson.h>
#include <stdio.h>
void main()
{
json_t *aa, *bb, *cc, *dd;
aa = json_load_file ("/home/cuihaikuo/demo.json", JSON_STRICT, NULL);
bb = json_array_get (aa, 0);
if (bb != NULL)
json_decref (bb);
if (aa != NULL)
json_decref (aa);
}
I use vargrind running the program, it says Invalid write of size 8
==2641== Invalid write of size 8
==2641== at 0x4E4201A: json_delete (in /usr/lib/x86_64-linux-gnu/libjansson.so.4.7.0)
==2641== by 0x4006C3: json_decref (in /home/cuihaikuo/chk/test/a)
==2641== by 0x400721: main (in /home/cuihaikuo/chk/test/a)
==2641== Address 0x5412438 is 8 bytes inside a block of size 48 free'd
==2641== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2641== by 0x4006C3: json_decref (in /home/cuihaikuo/chk/test/a)
==2641== by 0x40070E: main (in /home/cuihaikuo/chk/test/a)
if I comment out json_decref (aa);, it will lead a memory leak, how to explain it and what should I do?

json_array_get() returns a borrowed reference. You must not call json_decref() on the values that are returned as borrowed references, unless you manually call json_incref() to increase the reference count. In your minimalistic example, this is not required, so remove the json_decref (bb); and the code should work as expected.
However, if you need to use bb after you have released aa, then call json_incref (bb); after bb = json_array_get (aa, 0); and later, when you are done using bb, you can call json_decref (bb);
Also, even though json_array_get() doesn't mind being passed a NULL value, it would be nice to check the value of aa before using it, so readers of your code doesn't have to double check the manual to see if it is OK not to check aa before using it in json_array_get().

Related

C program, "Uninitialized Value Error" on initialized int array

Update:
Removing the print statement (line 52) entirely with all else the same as in the code below gave me 0 errors. The errors exist within my functions when printing (using philo[i]) and in this print statement (added for debugging), but do not exist if I run the entire program with no prints. Any ideas what I'm doing wrong???
Thank you for the help so far. I have made a couple of changes based on comments received so far.
***** Original (Edited) Question *****
I can't figure out why I have been getting this error, "Uninitialised value was created by a stack allocation". I started with a completed program that works fine, but gives me a ton of uninitialized value errors. I have traced the problem down to a few lines of code by excluding all functions and adding additional print statements. This code is to solve the dining philosopher's problem using threads (homework), so I don't want to post too much. My code is now:
#include <all needed header files>
#define NUM_PHIL 5
#define MIN_EAT_TIME 10
pthread_t philosopher[NUM_PHIL]; // array to hold IDs for philosopher threads
pthread_mutex_t chopstick[NUM_PHIL]; // array to hold IDs for chopstick mutexes (locks)
// function definitions here:
int philosopherFun(int *philo);
// All others have been bypassed at the time of my current problem
int main(int argc, char *argv[]) {
int phil[NUM_PHIL]; // Philosopher numbers ("names")
for(int i = 0; i < NUM_PHIL; i++) {
phil[i] = i + 1;
}
for(int i = 0; i < NUM_PHIL; i++) {
// Print statement causes valgrind error to exist (as does calling a function using phil)
printf("Value phil[%d] = %d\n", i, phil[i]);
}
// Initilize mutexes for chopsticks, report error as needed
for(int i = 0; i < NUM_PHIL; i++) {
if(pthread_mutex_init( stuff here) < 0) {
// error reporting
// print statement uses i
}
}
for(int i = 0; i < NUM_PHIL; i++) {
if(pthread_create(&philosopher[i], NULL, (void*) philosopherFun, (void*) &phil[i] ) != 0) {
// error reporting
// print statement uses phil[i]
}
}
/* Code omitted as this is Homework */
// Join threads created for philosophers (using pthread_join)
// error reporting
// print statement uses phil[i]
// Destroy chopstick mutexes when done. (using pthread_mutex_destroy)
// error reporting
// print statement uses i
printf("The philosophers have all finished eating and its time for bed. Goodnight...\n");
return 0;
}
int philosopherFun(int *philo) {
return 0;
}
Program output:
Value phil[0] = 1
Value phil[1] = 2
Value phil[2] = 3
Value phil[3] = 4
Value phil[4] = 5
The philosophers have all finished eating and its time for bed. Goodnight...
My Valgrind errors are:
==46556== HEAP SUMMARY:
==46556== in use at exit: 0 bytes in 0 blocks
==46556== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==46556==
==46556== All heap blocks were freed -- no leaks are possible
==46556==
==46556== ERROR SUMMARY: 10 errors from 1 contexts (suppressed: 0 from 0)
==46556==
==46556== 10 errors in context 1 of 1:
==46556== Conditional jump or move depends on uninitialised value(s)
==46556== at 0x7FFF205A395F: ??? (in /dev/ttys000)
==46556== by 0x7FFF2046FFFA: ??? (in /dev/ttys000)
==46556== by 0x7FFF20478CF0: ??? (in /dev/ttys000)
==46556== by 0x7FFF2049D8B8: ??? (in /dev/ttys000)
==46556== by 0x7FFF20475EF5: ??? (in /dev/ttys000)
==46556== by 0x7FFF20474061: ??? (in /dev/ttys000)
==46556== by 0x1000038CD: main (philo.c:52)
==46556== Uninitialised value was created by a stack allocation
==46556== at 0x7FFF20475FDF: ??? (in /dev/ttys000)
==46556==
==46556== ERROR SUMMARY: 10 errors from 1 contexts (suppressed: 0 from 0)
line 52 is my print statement:
printf("Value phil[%d] = %d\n", i, phil[i]);
which I believe accounts for 5 errors (phil[0] - phil[4]) and I call philosopherFun in my pthread_create on line 68 (this line of code included), again accounting for 5 errors (1 for each thread). This function is currently only returning on the first line, so none of the rest of my program is involved (though I started with 50-250 errors depending on my parameters and which functions I excluded).
I feel like my int array (int phil[]) is causing the problem, but it is immediately initialized, so I'm not sure how this is happening. Please help!
Thanks,
Kristine
Edited... Added some comments from omitted code- Threads are joined and mutexes destroyed
I also tried making int phil[NUM_PHIL] global by declaring it outside of my main function, but this made no change to the errors returned by Valgrind. defining phil[5] = {1, 2, 3, 4, 5}; as a global also didn't help.
I believe this is where your problem comes from:
int phil[NUM_PHIL];
and here
if(pthread_create(&philosopher[i], NULL, (void*) philosopherFun, (void*) &phil[i] ) != 0) {
more code ...
}
You're referencing a stack-allocated object (you're getting a pointer to the elements of the philo array). When the main function returns, the memory will be deleted and the other threads will still be holding on to garbage. To be sure this is the problem, move your philo array to a global scope, or allocate the array on the heap instead.

Segfault on calling a function in C

So I'm building a virtual machine, and trying to make it as cross platform as possible, and suddenly encountering a strange error. There is a let instruction for my machine, which allocates memory for a variable in the memory of the machine and assign that variable with a value. In short, the let function calls getAddress to get the address of the variable. getAddress checks if the variable is already defined, and returns the address. If the variable is not defined, getAddress calls memallocate to allocate memory for the variable, and returns the address. Here is the definition of the functions :
static uint16_t memallocate(Machine *m, char *symbol){
uint16_t allocationAddress = getFirstFree(*m);
SymbolTable *newSymbol = (SymbolTable *)malloc(sizeof(SymbolTable));
newSymbol->symbolName = strdup(symbol);
newSymbol->next = NULL;
newSymbol->mema = allocationAddress;
if(m->symbolTable==NULL){
m->symbolTable = newSymbol;
}
else{
SymbolTable *temp = m->symbolTable;
while(temp->next!=NULL)
temp = temp->next;
temp->next = newSymbol;
}
m->memory[allocationAddress].acquired = 1;
m->memory[allocationAddress].data.value = 0;
m->occupiedAddress++;
return allocationAddress;
}
uint16_t getAddress(Machine *m, char *symbol){
SymbolTable *table = m->symbolTable;
while(table!=NULL){
if(strcmp(symbol, table->symbolName)==0){
return table->mema;
}
table = table->next;
}
uint16_t address = memallocate(m, symbol); // Here is the segfault happening
return address;
}
This code compiles and runs pretty well on Linux, but on Windows I'm getting a segfault on the memallocate call. Since memallocate is directly passed the arguments of getAddress, and the arguments both being a pointer, they shouldn't change. But while debugging through CLion, I'm seeing gibberish arguments to the memallocate call, which is indicating some kind of stack violation(may be). Again, it is ONLY happening in Windows. Can anybody tell me what is going wrong with my code?
Full code for the project can be found at GitHub.
I took your code and run it on linux through valgrind:
==13768== Conditional jump or move depends on uninitialised value(s)
==13768== at 0x109ABE: getAddress (in /home/vonaka/VirtualMachine/machine)
==13768== by 0x10B714: let (in /home/vonaka/VirtualMachine/machine)
==13768== by 0x109425: run (in /home/vonaka/VirtualMachine/machine)
==13768== by 0x109F64: main (in /home/vonaka/VirtualMachine/machine)
==13768== Uninitialised value was created by a heap allocation
==13768== at 0x4C2BE7F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd
==13768== by 0x109C2F: main (in /home/vonaka/VirtualMachine/machine)
==13768==
So (luckily for us) it's not a Windows specific problem. The trick is that on the first call of getAddress (when m->symbolTable is NULL) you call getFirstFree(*m) at the beginning of memallocate, but look at this function:
static uint16_t getFirstFree(Machine m) {
uint16_t add = 0;
while(m.memory[add].acquired)
add++;
return add;
}
m.memory[i].acquired for i between 0 and number_of_instructions_in_your_input_file - 1are all equal to 1 as you initialize them in writeInstruction, but m.memory[number_of_instructions_in_your_input_file].acquired is not initialized yet.
So something like this will resolve your problem:
void writeInstruction(Machine *m, uint16_t add, Instruction ins) {
m->memory[add].acquired = 1;
m->memory[add].type = INSTRUCTION;
m->memory[add].data.instruction = ins;
m->occupiedAddress++;
if(add + 1 < NUM_MEM)
m->memory[add + 1].acquired = 0;
}
Or maybe this is more elegant (if it's works):
static uint16_t getFirstFree(Machine m) {
uint16_t add = 0;
while (m.memory[add].acquired && add < m.occupiedAddress)
add++;
return add;
}
Edit:
First of all about your comment:
By default, the members of the structure is initialised as 0
It's just not true!
Now about why you have segfault without malloc and how it's connected with valgrind's warning.
You have variable m of type Machine and some other variables in the stack, m contains Cell memory[NUM_MEM] and there is acquired in each Cell (which are not initialized!). Your input file contains let's say 88 instructions, so first 88 acquired will be correctly initialized after 88 calls of writeInstruction. Then program start to execute your instructions by calling some functions including memallocate and getFirstFree. In this loop:
while(m.memory[add].acquired)
add++;
for any add m.memory[add].acquired very likely can be different from 0, so once add is equal to NUM_MEM you have segfault.
Why it's not happening with malloc? Simply because you are lucky (but it's not a good luck), your heap is 'cleaner' than stack. Why it's happening only in Windows? Because this time you were not so lucky (I don't have segfault even in Windows).

HeapFree Breakpoint on Free()

I have a very large (~1E9) array of objects that I malloc, realloc, and free on iterations of a single thread program.
Specifically,
//(Individual *ind)
//malloc, old implementation
ind->obj = (double *)malloc(sizeof(double)*acb->in.nobj);
//new implementation
ind->obj = (double *)a_allocate(acb->in.nobj*sizeof(double));
void *a_allocate (int siz){
void *buf;
buf = calloc(1,siz);
acb->totmemMalloc+=siz;
if (buf==NULL){
a_throw2("a_allocate...failed to allocate buf...<%d>",siz);
}
return buf;
}
...
//realloc
ind->obj = (double *)a_realloc(ind->obj, acb->in.nobj*sizeof(double));
void *a_realloc (void *bufIn,int siz)
{
void *buf = bufIn;
if (buf==NULL){
a_throw2("a_realloc called with null bufIn...");
}
buf = realloc(buf,siz);
return buf;
}
...
//deallocate
free(ind->obj);
The other three dozen properties are processed similarly.
However, every few test runs, the code fails a heap validation on the deallocation of only this object property (the free() statement). At the time of failure, the ind->obj property is not null and has some valid value.
Is there any obvious problem with what I'm doing?
I'm very new to C and am not entirely sure I'm perform the memory operations correctly.
Thanks!
EDIT: using _CRTLDBG_REPORT_FLAG
HEAP[DEMO.exe]: Heap block at 010172B0 modified at 010172E4 past requested size of 2c
Heap validation is a delayed metric. The Visual Studio debug heap can be used (debug build) with more frequent checks Microsoft : Debug Heap flags.
Alternative using application verifier and turning on heap checking, will help find the point which is causing this.
+-----+----------+-----+ +----+-------------+-----+
| chk | memory |chk2 | | chk| different m | chk2|
+-----+----------+-----+ +----+-------------+-----+
When the system allocates memory, it puts meta- information about the memory before the returned pointer (or maybe after). When these memory pieces get overwritten, then that causes the heap failure.
This may be the memory you are freeing, or the memory which was directly before hand.
Edit - to address comments
A message such as "HEAP[DEMO.exe]: Heap block at 010172B0 modified at 010172E4 past requested size of 2c"
Implies that the memory at 01017280 wrote beyond the end of the allocated memory.
This could be because the amount malloced/realloced was too small, or an error in your loops.
+---+-----------------+----+--------------------------+
|chk|d0|d1|d2|d3|d4|d5|chk2| memory |
+---+-----------------+----+--------------------------+
So if you tried to write into d6 above, that would cause 'chk2' to be overwritten, which is being detected. In this case the difference is small - requested size is 0x2c and the difference = E4 - B0 = 0x34
Turning on these debug checks should change your code to be more crashing and predictable. If there is no randomness in your data, then turn off ASLR (only for debugging) and the addresses being used will be predictable, you can put a breakpoint in the malloc/realloc for a given memory address.

__memcpy_sse2_unaligned - what does this mean in detail?

While working on my compiler I got this error:
Program received signal SIGSEGV, Segmentation fault.
__memcpy_sse2_unaligned () at ../sysdeps/x86_64/multiarch/memcpy-sse2-unaligned.S:33
How do I get details of what went wrong here? I know from the backtrace it's a memcpy line that causes it, but how do I see how the memory is aligned? And how do I know how it should be aligned?
The project is a compiler with an LLVM back-end using the Zend/PHP runtime with the OCaml garbage collector, so there's is a lot of things that can go wrong.
I suspect this line being part of the problem:
zend_string *str = (zend_string *)caml_alloc(ZEND_MM_ALIGNED_SIZE(_STR_HEADER_SIZE + len + 1), 0);
where caml_alloc were pemalloc in the Zend source-code.
The segfault happens when doing 10'000 string concatenations. This is the output from valgrind:
==7501== Invalid read of size 8
==7501== at 0x4C2F790: memcpy##GLIBC_2.14 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7501== by 0x4D7E58: subsetphp_concat_function (bindings.c:160)
==7501== by 0x4D7F52: foo (llvm_test.s:21)
==7501== by 0x4D7FA9: main (llvm_test.s:60)
==7501== Address 0x61db938 is 2,660,600 bytes inside a block of size 3,936,288 free'd
==7501== at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7501== by 0x4C2627: do_compaction (in /home/olle/kod/subsetphp/test)
==7501== by 0x4C2735: caml_compact_heap (in /home/olle/kod/subsetphp/test)
==7501== by 0x4D08DF: caml_major_collection_slice (in /home/olle/kod/subsetphp/test)
==7501== by 0x4D2DCF: caml_minor_collection (in /home/olle/kod/subsetphp/test)
==7501== by 0x4D2FBC: caml_check_urgent_gc (in /home/olle/kod/subsetphp/test)
==7501== by 0x4D7C45: subsetphp_string_alloc (bindings.c:90)
==7501== by 0x4D7CEE: subsetphp_string_init (bindings.c:122)
==7501== by 0x4D7DEA: subsetphp_concat_function (bindings.c:149)
==7501== by 0x4D7F52: foo (llvm_test.s:21)
==7501== by 0x4D7FA9: main (llvm_test.s:60)
Any tips appreciated.
Edit:
extern value subsetphp_concat_function(value v1, value v2)
{
CAMLparam2(v1, v2);
zend_string *str1 = Zend_string_val(v1);
zend_string *str2 = Zend_string_val(v2);
size_t str1_len = str1->len;
size_t str2_len = str2->len;
size_t result_len = str1_len + str2_len;
value result = subsetphp_string_init("", result_len, 1);
zend_string *zend_result = Zend_string_val(result);
if (str1_len > SIZE_MAX - str2_len) {
zend_error_noreturn(E_ERROR, "String size overflow");
}
memcpy(zend_result->val, str1->val, str1_len); // This is line 160
memcpy(zend_result->val + str1_len, str2->val, str2_len);
zend_result->len = result_len;
zend_result->val[result_len] = '\0';
CAMLreturn(result);
}
Edit 2:
Since valgrind gives me this line
Address 0x61db938 is 2,660,600 bytes inside a block of size 3,936,288 free'd
I guess I'm trying to copy something that has already been freed, meaning that I don't tell the OCaml GC correctly when something is no longer referenced.
This errors tells you that something bad happen during memcpy, probably something like a null pointer or error in the sizes.
Don't bother with __memcpy_sse2_unaligned, it is an implementation detail of memcpy. memcpy has a lot of different implementation optimized for the different cases and dispatch dynamically to the most efficient one given the context. That one seems to be used when sse2 instructions are available and pointers are not alligned to 16 bytes boundaries (sse2 instructions cannot load unaligned values), which is probably done by copying one byte at a time until a 16 byte boundary is reached then switching to the fast path.
As for the OCaml gc specific details linked with LLVM, you need to be quite carefull to how you handle heap pointers. As you don't tell whether you are using the gcroot mechanism or the new statepoints, I will suppose you are using gcroot.
Since the OCaml gc is a moving collector (moving from minor heap to major heap, and moving during compaction) every allocation can potentially invalidate a pointer. That means that it is usualy unsafe to factorise field access to heap allocated values. For instance this is unsafe:
v = field(0, x)
r = function_call(...)
w = field(0, v)
the function call could do some allocations that could trigger a compaction.
v = field(0, x)
r = function_call(...)
v' = field(0, x)
w = field(0, v')
By the way, I'm not even certain that the gcroot mechanism can correctly handle moving gc (that llvm doesn't optimize things it shouldn"t).
So that usualy means that it's not a good idea to use gcroot with OCaml's GC. The new way is better for that kind of GC, but you still need to be carefull not to access pointer across function calls or allocations.
So your error may be something linked to that kind of problem: the pointer was valid at some point, then a value was moved during compaction that resulted in some gc page being unused, hence freed.

Getting Segmentation Fault in C program

I am getting segmentation fault on line 8 in the code below.
typedef struct _my_struct {
int pArr[21];
int arr1[8191];
int arr2[8191];
int m;
int cLen;
int gArr[53];
int dArr[8191];
int data[4096];
int rArr[53];
int eArr[1024];
};
void *populate_data(void *arg) {
1 register int mask =1, iG;
2 struct _my_struct *var ;
3 var = arg; // arg is passed as initialized struct variable while creating thread
4 var->m = 13;
5 var->arr2[var->m] = 0;
6 for (iG = 0; iG < var->m; iG++) {
7 var->arr2[iG] = mask;
8 var->arr1[var->arr2[iG]] = iG;
9 if (var->pArr[iG] != 0) // pArr[]= 1011000000001
10 var->arr2[var->m] ^= mask;
11 mask <<= 1;
12 }
13 var->arr1[var->arr2[var->m]] = var->m;
14 mask >>= 1;
15 for (iG = var->m+ 1; iG < var->cLen; iG++) {
16 if (var->arr2[iG - 1] >= mask)
17 var->arr2[iG] = var->arr2[var->m] ^ ((var->arr2[iG- 1] ^ mask) << 1);
18 else
19 var->arr2[iG] = var->arr2[iG- 1] << 1;
20 var->arr1[var->arr2[iG]] = iG;
21 }
22 var->arr1[0] = -1;
}
Here is the thread function:
void main() {
unsigned int tid;
struct _my_struct *instance = NULL;
instance = (struct _my_struct *)malloc(sizeof(_my_struct ));
start_thread(&tid , 119312, populate_data, instance );
}
int
start_thread(unsigned int *tid, int stack_size, void * (*my_function)(void *), void *arg)
{
pthread_t ptid = -1;
pthread_attr_t pattrib;
pthread_attr_init(&pattrib);
if(stack_size > 0)
{
pthread_attr_setstacksize(&pattrib, stack_size);
}
else
{
pthread_attr_destroy(&pattrib);
return -1;
}
pthread_create(&ptid, &pattrib, my_function, arg);
pthread_attr_destroy(&pattrib);
return 0;
}
Once I debug it through gdb, got this error,
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffdfec80700 (LWP 22985)]
0x0000000000401034 in populate_data (arg=0x7fffffffe5d8) at Queue.c:19
19 var->arr1[var->arr2[iG]] = iG;
and its backtrace is:
#0 0x0000000000401034 in populate_data (arg=0x7fffffffe5d8) at Queue.c:159
#1 0x00007ffff7bc6971 in start_thread () from /lib/libpthread.so.0
#2 0x00007ffff792292d in clone () from /lib/libc.so.6
#3 0x0000000000000000 in ?? ()
However, I'm unable to correct the error.
Anyhelp is really appreciated.
Please show the calling code in start_thread.
It seems likely to be a stack and/or memory allocation error, the structure is pretty large (8 MB assuming 32-bit ints) and might well overflow some stack limit.
Even more possible is that it's gone out of scope, which is why the calling step must be shown.
I don't know if perhaps you've changed the names of the arrays in your _my_struct in order to hide the purpose of them (company confidential information, perhaps?), but if that's actually what you've named your arrays, I'm just going to suggest that you name them something that makes sense to you that when someone has to read your code 4 years from now, they'll have some hope of following your initialization loops & understanding what's going on. Same goes for your loop variable iG.
My next comment/question is, why are you firing off a thread to initialize this structure that's on the stack of the main thread? Which thread is going to be using this structure once it's initialized? Or are you going to make other threads that will use it? Do you have any mechanism (mutex? semaphore?) to ensure that the other threads won't start using the data until your initialization thread is done initializing it? Which sort of begs the question, why the heck are you bothering to fire off a separate thread to initialize it in the first place; you could just initialize it by calling populate_data() straight from main() and not even have to worry about synchronization because you wouldn't even be starting up any other threads until after it's done being initialized. If you're running on a multicore machine, you might get some small benefit from firing off that separate thread to do the initialization while main() goes on & does other stuff, but from the size of your struct (not tiny, but not huge either) it seems like that benefit would be very miniscule. And if you're running on a single core, you'll get no concurrency benefit at all; you'd just be wasting time firing off another thread to do it due to the context switching overhead; in a unicore environment you'd be better off just calling populate_data() directly from main().
Next comment is, your _my_struct is not huge, so it's not going to blow your stack by itself. But it ain't tiny either. If your app will always need only one copy of this struct, maybe you should make it a global variable or a file-scope variable, so it doesn't eat up stack space.
Finally, to your actual bug............
I didn't bother to try to decipher your cryptic looping code, but valgrind is telling me that you have some conditions that depend on uninitialized locations:
~/test/so$ valgrind a.out
==27663== Memcheck, a memory error detector
==27663== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==27663== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==27663== Command: a.out
==27663==
==27663== Thread 2:
==27663== Conditional jump or move depends on uninitialised value(s)
==27663== at 0x8048577: populate_data (so2.c:34)
==27663== by 0x593851: start_thread (in /lib/libpthread-2.5.so)
==27663== by 0x4BDA8D: clone (in /lib/libc-2.5.so)
==27663==
==27663== Conditional jump or move depends on uninitialised value(s)
==27663== at 0x804868A: populate_data (so2.c:40)
==27663== by 0x593851: start_thread (in /lib/libpthread-2.5.so)
==27663== by 0x4BDA8D: clone (in /lib/libc-2.5.so)
My so2.c line 34 corresponds with line 9 in your code posting above.
My so2.c line 40 corresponds with line 15 in your code posting above.
If I add the following at the top of populate_data(), these valgrind errors disappear:
memset(arg,0,sizeof(_my_struct_t));
(I modified your struct definition as follows:)
typedef struct _my_struct { int pArr[21]; ......... } _my_struct_t;
Now just because adding the memset() call makes the errors disappear doesn't necessarily mean that your loop logic is correct, it just means that now those locations are considered "initialized" by valgrind. If having all-zeros in those locations when your initialization loops begin is what your logic needs, then that should fix it. But you need to verify for yourself that such really is the proper solution.
BTW... someone suggested using calloc() to get a zeroed-out allocation (rather than using dirty stack space)... that would work too, but if you want populate_data() to be foolproof, you'll zero the memory in it and not in the caller, since (assuming you like your initialization logic as it is), populate_data() is the thing that depends on it being zeroed out, main() shouldn't have to care whether it is or not. Not a biggie either way.

Resources