I'm writing a very simple code in which i need to use some threads.
When I create first type of thread i pass argument with pthread_create:
fman thread_arg;
thread_arg.sd=sda;
char* split = strtok(buffer, "|");
thread_arg.wcount=atoi(split);
split = strtok(NULL,"");
strcpy(thread_arg.id, split);
pthread_create(&thread_temp, NULL, registerF, &thread_arg);
And everything works fine, but in function registerF I need to do something like this:
wman thread_arg;
thread_arg.sd=foremans_fd[ix];
thread_arg.fmanix=ix;
strcpy(thread_arg.id,tmpr);
pthread_create(&thread_temp, NULL, registerW, &thread_arg);
Those arguments are structures defined by me:
typedef struct fman
{
int sd;
char id[100];
int wcount;
} fman;
typedef struct wman
{
int sd;
int fmanix;
char id[100];
} wman;
And when I check it by printf("%x, args) I get the same address but values are different inside. Where is my mistake?
One likely problem is here:
fman thread_arg;
[...]
pthread_create(&thread_temp, NULL, registerF, &thread_arg);
Note that the thread_arg object is located on the stack, and thus will be destroyed (and likely overwritten by other stack variables) when the function it is declared in returns.
pthread_create(), on the other hand, launches a thread that will run asynchronously with this function, which means that the thread can (and often will) run after the function you excerpted has returned, which means that by the time the thread dereferences &thread_arg, thread_arg has likely already been destroyed and that pointer is now pointing to some other data that was written into the same stack location later on.
Unless you are doing something special to make sure that the struct's lifetime is long enough to include all of the spawned thread's accesses to the struct, then the fact that this code ever works is pure luck (i.e. the scheduler just happened to schedule the thread to run and perform all of its accesses to the struct before the struct was destroyed/overwritten). You definitely can't depend on that.
In order to fix the problem, you need to either allocate the struct on the heap (so that it won't be destroyed when the function returns -- the spawned thread can then free the struct when it is done using it), or use some kind of synchronization mechanism (e.g. a condition variable) to cause the main thread to block inside your function until the spawned thread has indicated that it is done accessing the struct.
The thread struct in the running thread is treated like a block of memory and accessed using offsets. Since your fman and wman structs have different orders (4+100+4) vs (4+4+100), it's likely that you're getting right struct but reading from different memory location, given the passed struct to this thread is fman, and it's being accessed as wman.
Try changing them both to same signature, as in, int, int, char* and it should work.
Related
I have an struct variable which is passed like as follows:
//function definition
void function1(const Node* aVAR1)
{
Node* value=NULL;
.....
}
int main()
{
Node* aVAR=NULL;
aVAR=x.value;
function1(aVAR);
}
Here, when I run this in gdb, and step into function1(), I see for variable aVAR one temporary memory address is created.
GDB:
21 aVAR=x.value;
(gdb) p aVAR
$5 = (Node *) 0x654321
(gdb) n
Breakpoint 1, function1(aVAR1=0x7ffffffffebcdf ) at debug/../abc.c:12
12 {
(gdb) p aVAR1
$6 = (const Node *) 0x7ffffffffebcdf
For example,
Initially, the address of aVAR is 0x654321
Later for a short while until the first instruction in function1() is not executed, aVAR1 is kept in some temporary address like 0x7ffffffffebcdf.
After executing Node* value=NULL; which is first instruction in the function1(), the aVar1's address is 0x654321 again.
but this temporary (0x7ffffffffebcdf) address is not cleaned up: even after the function exits, 0x7ffffffffebcdf is not cleared
I want 0x7ffffffffebcdf to be cleared after function exits but that 0x7ffffffffebcdf address does not have a pointer through which I can access this memory. Is there any option while linking in GCC through which I can prevent this?
If I add a malloc for aVAR and clear it later using memset and free, the problem gets resolved BUT logically when I see , I lose the reference to the memory block allocated by malloc() , and I won't be able to free() the allocated memory (causing memory leak ).
In what you presented, you have two variables called aVAR. The first is local var in main, and the second is function1's parameter. Both are in automatic storage (or "temporary" storage, as you call it), and thus will cease to exist when the function containing them exits. Nothing special needs to be done to free them.
Only the pointed structure needs to be freed (assuming it was malloc'ed), and that only needs to be done once, no matter how many pointers you had to it in its lifetime.
In short, all you need is one free per malloc/calloc. (Though keep in mind that strdup will call malloc, and passing NULL to realloc is effectively a malloc.)
I want 0x7ffffffffebcdf to be cleared after function exits...
I have a limited imagination, but among the reasons I can imagine you want this is:
You think that this is still in use; it isn’t, it is out of scope, and unreachable.
If it happens to be reachable, because you have stored its address somewhere, you have made a mistake that no amount of zeroing will cure.
You have a security issue, and you want to make sure temporary memory is scrubbed.
So, given [3] there are two choices; change your code to zero it before main returns; or change your main() to be mymain():
int mymain() {
Node* aVAR=NULL;
aVAR=x.value;
function1(aVAR);
return something;
}
void clearstack() {
int data[1000];
int fd;
if ((fd = open("/dev/zero", O_RDONLY)) != -1) {
read(fd, data, sizeof data);
close(fd);
}
}
int main() {
int r = mymain();
clearstack();
return r;
}
this works because the stack addresses will overlay between the two function calls, so your 0x7f-febcdf will land in the middle of data[]. The choir of implementation defined behaviour should be warming up now.
but really, you would be better off with:
int mymain() {
Node* aVAR=NULL;
aVAR=x.value;
function1(aVAR);
aVAR = 0;
dummyfunction(&aVAR);
return aVAR == 0;
}
Note that by providing the address of aVAR to dummyfunction, you preturb the compilers ability to remove what it might consider useless. This sort of behavior is difficult to predict, however, because it binds your program source to whatever version of whatever compiler is at your disposal; not a great prospect.
If volatile had any sort of rigor in its definition, it would be useful here, but it hasn't.
A little better would be to use malloc() to acquire the variable, then you are bound by a contract that this is memory [ whereas a local variable could be register only ], and you can scrub it before freeing it. It would be at the outer reaches of unacceptable behavior for the compiler to optimize out the scrub. It still might leave data sitting in some registers, which might leak out.
All this said; if an attacker is really out for uncovering secrets that are plaintext in your program, you might not be able to stop them. They could start your program under a debugger or hypervisor, and inspect the data at will.
There are concepts in some modern processors where the cpu can construct a sort of enclave where secrets can be safely unwrapped; but there are many flaws. ARM TrustZone's Secure/Normal world vs. OS's kernel/user mode or x86's Ring0/1/2/3? has more info.
I have a question about passing a struct to a function without declaring the struct first.
I have a function that takes a struct pointer like this:
static void DrawArc(struct MATH_POINT *p, other args);
I know I can pass a structure like this
struct MATH_POINT point = {0,0};
DrawArc(&point, other args);
But I can also do it like this:
DrawArc(&(struct MATH_POINT){0,0}, other args);
I am doing it this way because I am on an embedded platform with very limited register space, and my GUI functions require many arguments.
But my worry is that the structures I initialized in the argument list will stick around and use up RAM. Is this possible? Or will the struct be destroyed as soon as the function finishes?
Thanks!
You are mixing and matching things. Any object which is not explicitly instantiated with malloc/calloc/etc but it is instantiated locally won't take any heap memory, it will just make the stack grow until the variable exits the scope.
Your first example:
struct MATH_POINT point = {0,0};
DrawArc(&point, other args);
is perfectly fine. point will be allocated on stack, it won't take more memory than the one needed to store itself and it will be automatically released upon exiting the scope of declaration.
In any case, in both your examples, since there is no dynamic allocation, there's no risk of leaving things around.
struct MATH_POINT point = {0,0};
DrawArc(&point, other args);
this point variable will live longer than this
DrawArc(&(struct MATH_POINT){0,0}, other args);
since the first one's scope is still alive after calling DrawArc, while the second is discarded as soon as the function returns. (and: Neither of them "stick around", both have a well defined lifecycle ;-) )
if you want to "remove" a variable, add an additional scope, and close it if you don't need it anymore:
#define MANY 10000
{
struct MATH_POINT removeMe[MANY];
/* work on removeMe while they're alive */
doThings(removeMe, other_stuff);
}
/* here removeMe is gone, and the mem can/will be used otherwise */
My question regards parameter passing to a thread.
I have a function Foo that operates on an array, say arrayA. To speed things up, Foo is coded to operate at both directions on the array. So, Foo takes arrayA and an integer X as parameters. Depending on the value of X, it operates in forward or reverse direction.
I'm looking to avoid making global use of "arrayA" and "X". So, I'm after passing "arrayA" and "X" as parameters to Foo, and creating two threads to run Foo-- one in each direction. Here's what I did:
typedef struct {int* arrayA[MSIZE]; int X; } TP; //arrayPack=TP
void Foo (void *tP) {
TP *tp = (TP*)tP; // cast the parameter tP back to what it is and assign to pointer *tp
int x;
printf("\nX: %d", tp->X);
printf("\n arrayA: "); for (x=0; x<tp->arrayA.size(); printf("%d ", aP->arrayA[x]), x++);
} // end Foo
void callingRouting () {
int* arrayA[MSIZE] = {3,5,7,9};
TP tp; tp.arrayA=arrayA;
tp.X=0; _beginthread(Foo, 0, (void*)&tp); // process -- forward
tp.X=1; _beginthread(Foo, 0, (void*)&tp); // process -- reverse
}
The values aren`t passed-- my array is printing empty and I'm not getting the value of X printed right. What am i missing ?
I would also appreciate suggestions on some readings on this-- passing parameters to threads-- especially on passing the resources shared by the threads. Thanks.
You're passing the address of a stack variable to your thread function, once callingRouting exits the TP structure no longer exists. They need to be either globals or allocated on the heap.
However you'll need two copies of the TP for each thread as the change tp.X=1 may be visible to both threads.
There are problems there but how you see them depends on how the OS decides to schedule the threads on each execution.
The first thing to remember is that you have a thread that is starting up two other threads. Since you do not have any control over the processor time slice and how that is allocated, you can not be sure when the two other threads will start and may be not even the order that they will start in.
Since you hare using an array on the stack that is local to the function callingRouting () as soon as that function returns the local variables allocated will basically be out of scope and can no longer be depended on.
So there are a couple of ways to do this.
The first is to use global or static memory variables for these data items being passed to the threads.
The other is to start both threads and then wait for both to complete before continuing.
Since you do not know when or the order of the threads being started, you really should use two different TP type variables, one for each thread. Otherwise you run the risk of the time slice allocation to be such that both threads will have the same TP data.
I am trying to pass a struct as a parameter to pthread_create and seem to be getting some strange results.
The struct has two members, first one being an int and the second one is a function pointer:
typedef struct
{
int num;
void (*func)(int);
} foo_t;
The function I am trying to use within the struct:
void myfunc(int mynum)
{
printf("mynum: %d\n", mynum);
}
This is the declaration of the struct I will be passing to my thread:
foo_t f;
f.num = 42;
f.func = &myfunc;
The call to pthread_create:
pthread_create(&mythread, NULL, mythreadfunc, &f);
And finally, my thread function:
void mythreadfunc(void *foo)
{
foo_t f = *(foo_t *)foo;
printf("num: %d\n", f.num); // Prints: num: 32776 (undefined?)
(*f.func)(f.num); // Segfaults (again, undefined?)
...
It seems that the cast within mythreadfunc doesn't seem to work and I can't figure out why. Any suggestions? Thanks.
Papergay's answer is definitely one solution, but another approach you can use if you want to avoid dynamic allocation is just using synchronization. My favorite approach is putting a semaphore with initial-value zero in the struct and having the parent wait on the semaphore and the child post the semaphore after it's done reading the values out of the structure.
You are passing your foo_t f by reference. If you are changing your f from your pthread_create-calling function or somewhere else, for example leaving the corresponding scope would remove/delete f from the stack, then your reference inside your thread is (most likely) invalid. At least you should not access it anymore.
Use pointers with dynamically allocated variables instead.
Though I can not prove that this is happening with the code you have presented.
Edit:
A pointer is used to store the address of an object/variable. In C/C++ you can have it point to a dynamically allocated memory segment. Look up malloc/new for this. You can do what is called dereferencing with pointers and access the objecct/variable itself.
You can pass the pointer per value, which means, that you won't pass the object/variable itself, but the address(= position) of the object/variable inside your RAM. The memory management of dynamically allocated varialbes/object lies in the responsibility of the programmer, so your object won't be deleted when the scope of the pointer ends, only the pointer which stores the address will be deleted.
This is my struct:
struct example {
int c=0;
char buf[10];
}
I have a struct of this type allocated in main()
...
struct example *ex=malloc(sizeof(*ex));
...
and passed to a thread by
...
pthread_create(&id[i], NULL, t_func, ex);
...
pthread_create is called into a child of main.
t_func is:
void *t_func(void* args) {
struct example *extmp = args;
....
How can I create a local struct example in every thread and copy into it the struct and the values of args? I need it such that if I modify a field of the local struct, that will not be seen in other threads. I've seen other similar questions, but I haven't found my answer...
In C you can assign objects of structure type:
struct example *extmp = args;
struct example local_copy = *extmp;
If you want a clean, unshared copy for each thread, the place to make the copy is before passing it to the thread. This avoids issues with needing to lock the data.
In your case, the main function should malloc another struct, then you can use memcpy or *new_data = *old_data to copy the data. Then you pass the pointer into the thread.
Now this is the important part. The main thread should never touch that copy again. The thread should call free when it is done using the data.
Yes, this means that you still have a pointer to a struct and not a struct on the thread stack. However, think about it: what does a struct on the stack get you? You have to type -> instead of . and that's about it.
Of course, my advice gets a lot more complicated and develops exceptions and curlicues if you are doing memory allocation with lock-free per-thread pools or NUMA. In those cases you probably do want to make the copy inside the thread. The main data will need to be locked and the thread will need to make its copy then unlock the data source.
In some exciting case you may need three copies: the primary copy (main memory), a temporary copy (main memory but no need to lock the primary) and the in-thread copy (now in per-thread memory, also no locks).