Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert a void* back into an array

I have a char* array which gets converted to void*, but I am having difficulty accessing the original array. See the args array:

void run_async(char* src, char* dest) {
  char* args[] = {src, dest};
  _beginthreadex(NULL, 0, copyFile, args, NULL, 0);
}

unsigned __stdcall copyFile(void* args) {
  char* src = (char*)((char*)args)[0]; //!Not correct
}

My mind is having trouble wrapping around these pointers. How do I access array location 0 and 1 in the copyFile() function?

Edit: On coderpad the function works with the updated cast (char**) but during program execution with threadding it does not

like image 636
dukevin Avatar asked May 20 '26 07:05

dukevin


1 Answers

You must cast args to char **, because args is a pointer to the first element, which itself is a char *. So you have a so-called "double pointer", i.e. a pointer to a pointer. After that, you can use the [] subscript operator on it, and the second type cast is unnecessary.

The reason why the code you linked to in the comments section works, but the code in your original question doesn't, is probably the following reason: The lifetime of the array args in the function run_async is limited to the lifetime of the function run_asyc. You therefore have a race condition. If the function run_async exits before copyFile reads the array, then the array may have meanwhile been overwritten by something else.

To prevent this race condition, you should ensure that the lifetime of the array exceeds that of the thread created by _beginthreadex, for example by

  1. using a global array (simplest solution, but sometimes considered bad programming practice), or

  2. allocating the array in the function main instead of run_async, or

  3. allocating the array with new[] or malloc and only calling delete[] or free after the second thread has terminated, or by making the second thread responsible for calling delete[] or free when the array is no longer required.

However, as pointed out in the comments section, using a C-style array and calling the function _beginthreadex is not the ideal way to solve your problem in modern C++. If you use std::thread instead of _beginthreadex and use std::array instead of a C-style array, then you can simply pass the array by value to the new thread. That way, you don't have to worry about freeing the memory of the array, because there is no dynamic memory allocation. This solution also has the advantage that your code will be portable, as you are no longer using platform-specific functions.

like image 114
Andreas Wenzel Avatar answered May 23 '26 00:05

Andreas Wenzel