Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C++
Are static functions without static variables thread-safe? Is there a website that lists what C/C++ functions are not thread-safe?
 
For example,
 
static void Split_Into_Path_And_File(char * const SaveAs,
                                     std::string & Path,
                                     std::string & File) {
    std::string const temp(SaveAs);
    //find the folder name to use to name the 7z file
    size_t last=temp.find_last_of('\\');
    File=temp.substr(last+1, temp.size()-last-1);
    Path=temp.substr(0, last);
}
 
Am I correct assuming that static function constants (not in classes) and constant arrays thread-safe as well?
 
For example,
 
static int const X=5;
static Increment[WEEKDAYS_IN_WEEK+WEEKDAYS_IN_WEEK]= { 1, 1, 1, 1, 3, 1, 1, 1, 1, 3 };
 

I am trying to figure out why my ADO .NET code with _stdcall interface massively leaks memory when called with multiple threads from multi-threaded exe without run-time support.
Posted 21-Sep-10 4:47am
T21024.3K
Edited 21-Sep-10 5:40am
v3
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

It depends on how they're written. If you do everything carefully you can get away with it. However you really have to link with the multi-threaded runtime or it can all end in tears. Seeing as with C++ you haven't been able to use a single threaded runtime since 2005 with VC++ maybe a compiler upgrade is in order?
 
In the example you've given you're potentially allocating memory in three out of four lines in that function - if you're not linking with the multi-threaded runtime you can easily end up with problems when:
 
- the standard string constructor or assignment operator uses the same block of memory for two different objects (something will probably crash)
 
- two strings in different threads go out of scope at the same time, the last one to free the memory sticks and the second is lost
 
So make sure that you use the mutithreaded runtime, don't share objects between threads or make sure they're properly synchronised.
 
Cheers,
 
Ash
 
PS: With respect to the "answer" you gave below - the function above is not thread safe. If two threads enter it at the same time chaos may (or not) ensue. If you want to make it thread safe either do what Paul suggested and get rid of the reference parameters OR lock the function so only one thread can be in it at one time. I'd do what Paul suggested as locking in this sort of case can really burn any parallel speedup for your code.
  Permalink  
v2
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 3

Wait a second... Accessing the objects Path and File is by no means thread-safe. It depends on whether several threads may share these instances or not.
 
A thread safe version would be this one, for example (of course under the assumption you are using a thread safe version of the runtime lib):
static std::pair<std::string, std::string>
Split_Into_Path_And_File
( char * const SaveAs ) {
    std::string const temp(SaveAs);
    //find the folder name to use to name the 7z file
    size_t last=temp.find_last_of('\\');
    return std::make_pair(
     temp.substr(last+1, temp.size()-last-1);
     temp.substr(0, last));
}
 
Edited by Ash to get rid of the redundant extra parameter to the function
  Permalink  
v3
Comments
Ted2102 at 22-Sep-10 0:25am
   
I am running several threads at once. Can you tell me why is passing in std::string & Path and std::string & File in a void function is not thread-safe? I will check if I am using fopen elsewhere and whether that is thread-safe.
paul_71 at 22-Sep-10 18:03pm
   
Because both are references to objects which are "non-local" from the function's perspective. If this function is executed concurrently by different threads you might get a race condition when writing to Path and/or File. With the above version, only a thread local (stack) object is generated, hence it's thread safe.
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

Glad that I am using Visual Studio 2010 then. Thanks for letting me know that the above function should be thread safe as long as I use multi-threaded run-time.
  Permalink  
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 5

you can use CriticalSection,
for example, if you use MFC, the code may like below:
<pre lang="cs">#include "afxmt.h"
CCriticalSection critical_section;
 
static void Split_Into_Path_And_File(char * const SaveAs,
std::string & Path,
std::string & File)
{
std::string const temp(SaveAs);
critical_section.Lock();
//find the folder name to use to name the 7z file
size_t last=temp.find_last_of('\\');
File=temp.substr(last+1, temp.size()-last-1);
Path=temp.substr(0, last);
critical_section.Unlock();
}
  Permalink  
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 4

This function is thread-unsafe just like any other C/C++ function that takes reference or pointer. The function atoi, for example is prone to multi-threading issues.
  Permalink  
Comments
Aescleal at 27-Sep-10 15:42pm
   
So if I write a function:
 
void f( A &a )
{
a.do_something();
a.do_something_else();
}
 
How can you tell that's unsafe without examining the code for A? While you can say "Aliasing data between threads is a good way of causing threading issues" saying a function can't be thread safe because it takes a reference or pointer is completely specious.
Ajay Vijayvargiya at 27-Sep-10 22:58pm
   
char buffer[10]; // Global
...
// thread 1.
int n1 = atoi(buffer);
 
// thread 2
int n2 = atoi(buffer);
 
Isn't it thread-unsafe? This is the whole point. Unless you guard the function or the object yourself, it is unsafe!
paul_71 at 28-Sep-10 2:15am
   
No, it's not since atoi is read-only operation.. Writing to 'buffer' is inherently thread unsafe. You cannot generalize that to the above statement. In Ash's example, A::do_something could be designed to be thread safe. The function from the first example is not safe if looking at it alone: the assignment to a std::string& is not thread-safe. However, if used in thread local context it could be safe to use it, for example:
 
class A {
private:
void Split_Into_Path_And_File(...);
//...
public:
void DoWork() {

ThreadPool.StartNew([] -> (const char* str) {
std::string p, f;
Split_Into_Path_And_File(str, p, f);
DoSomethingThreadSafe(p, f);
});
}
}; // A end

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
0 OriginalGriff 280
1 Jochen Arndt 150
2 Kornfeld Eliyahu Peter 120
3 PIEBALDconsult 110
4 Richard MacCutchan 105
0 OriginalGriff 6,055
1 DamithSL 4,621
2 Maciej Los 4,087
3 Kornfeld Eliyahu Peter 3,500
4 Sergey Alexandrovich Kryukov 3,294


Advertise | Privacy | Mobile
Web01 | 2.8.141220.1 | Last Updated 27 Sep 2010
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100