Finding recursion with any amount of determinism at compile time will be quite difficult. Some static code analysis tools can do this, but even then, you can move on to run-time scripts involving threads that code analyzers cannot detect.
You must detect recursion at runtime. In fact, this is very simple:
bool MyFnSimple()
{
static bool entered = false;
if( entered )
{
cout << "Re-entered function!" << endl;
return false;
}
entered = true;
entered = false;
return true;
}
, , , -. , - , . Windows ( ):
bool MyFnCritSecBlocking()
{
static HANDLE cs = CreateMutex(0, 0, 0);
WaitForSingleObject(cs, INFINITE);
ReleaseMutex(cs);
return true;
}
, , :
bool MyFnCritSecNonBlocking()
{
static HANDLE cs = CreateMutex(0, 0, 0);
DWORD ret = WaitForSingleObject(cs, 0);
if( WAIT_TIMEOUT == ret )
return false;
ReleaseMutex(cs);
return true;
}
, , bools critsecs. Windows:
bool MyFnInterlocked()
{
static LONG volatile entered = 0;
LONG ret = InterlockedCompareExchange(&entered, 1, 0);
if( ret == 1 )
return false;
InterlockedExchange(&entered, 0);
return false;
}
, , . , . RAII, .
:
, , , RAII, , , RAII . RAII, , , - :
#include <windows.h>
#include <cstdlib>
#include <stdexcept>
#include <iostream>
class CritSecLock
{
public:
CritSecLock(HANDLE cs) : cs_(cs)
{
DWORD ret = WaitForSingleObject(cs_, INFINITE);
if( ret != WAIT_OBJECT_0 )
throw std::runtime_error("Unable To Acquire Mutex");
std::cout << "Locked" << std::endl;
}
~CritSecLock()
{
std::cout << "Unlocked" << std::endl;
ReleaseMutex(cs_);
}
private:
HANDLE cs_;
};
bool MyFnPrimitiveRAII()
{
static HANDLE cs = CreateMutex(0, 0, 0);
try
{
CritSecLock lock(cs);
throw std::runtime_error("kerflewy!");
return true;
}
catch(...)
{
std::cout << "ErrorDetected" << std::endl;
return false;
}
}
int main()
{
MyFnPrimitiveRAII();
return 0;
}