C++ Visual Studio 2013 Unwinding object - c++

Well, I'm trying to build this line of code, bit I get a compiler error. I've tryed to build without the compiler, but that didn't work either. Its about the __try and __except. Someone told me to move the code in the try block to another function. But I don't understand this:
Error 12 error C2712: Cannot use __try in functions that require
object unwinding
Error 437 error LNK1181: cannot open input file
void MSocketThread::Run()
{
__try{
//throw(pThread);
while (true) { // Waiting for SafeUDP Settting...
DWORD dwVal = WaitForSingleObject(m_KillEvent.GetEvent(), 100);
if (dwVal == WAIT_OBJECT_0) {
return;
}
else if (dwVal == WAIT_TIMEOUT) {
if (m_pSafeUDP)
break;
}
}
WSAEVENT EventArray[WSA_MAXIMUM_WAIT_EVENTS];
WORD wEventIndex = 0;
bool bSendable = false;
WSANETWORKEVENTS NetEvent;
WSAEVENT hFDEvent = WSACreateEvent();
EventArray[wEventIndex++] = hFDEvent;
EventArray[wEventIndex++] = m_ACKEvent.GetEvent();
EventArray[wEventIndex++] = m_SendEvent.GetEvent();
EventArray[wEventIndex++] = m_KillEvent.GetEvent();
WSAEventSelect(m_pSafeUDP->GetLocalSocket(), hFDEvent, FD_READ | FD_WRITE);
while (TRUE) {
DWORD dwReturn = WSAWaitForMultipleEvents(wEventIndex, EventArray, FALSE, SAFEUDP_SAFE_MANAGE_TIME, FALSE);
if (dwReturn == WSA_WAIT_TIMEOUT) { // Time
m_pSafeUDP->LockNetLink();
SafeSendManage();
m_pSafeUDP->UnlockNetLink();
}
else if (dwReturn == WSA_WAIT_EVENT_0) { // Socket Event
WSAEnumNetworkEvents(m_pSafeUDP->GetLocalSocket(), hFDEvent, &NetEvent);
if ((NetEvent.lNetworkEvents & FD_READ) == FD_READ) {
// OutputDebugString("SUDP> FD_READ \n");
m_pSafeUDP->LockNetLink();
Recv();
m_pSafeUDP->UnlockNetLink();
}
if ((NetEvent.lNetworkEvents & FD_WRITE) == FD_WRITE) {
bSendable = true;
// OutputDebugString("SUDP> FD_WRITE \n");
}
}
else if (dwReturn == WSA_WAIT_EVENT_0 + 1) { // ACK Send Event
// OutputDebugString("SUDP> ACK_EVENT \n");
FlushACK();
}
else if (dwReturn == WSA_WAIT_EVENT_0 + 2) { // Packet Send Event
// OutputDebugString("SUDP> SEND_EVENT \n");
if (bSendable == true)
FlushSend();
}
else if (dwReturn == WSA_WAIT_EVENT_0 + 3) { // Kill the Thread
break; // Stop Thread
}
}
WSACloseEvent(hFDEvent);
// Clear Queues
LockSend();
{
for (SendListItor itor = m_SendList.begin(); itor != m_SendList.end();) {
delete (*itor);
itor = m_SendList.erase(itor);
}
}
{
for (SendListItor itor = m_TempSendList.begin(); itor != m_TempSendList.end();) {
delete (*itor);
itor = m_TempSendList.erase(itor);
}
}
UnlockSend();
LockACK();
{
for (ACKSendListItor itor = m_ACKSendList.begin(); itor != m_ACKSendList.end();) {
delete (*itor);
itor = m_ACKSendList.erase(itor);
}
}
{
for (ACKSendListItor itor = m_TempACKSendList.begin(); itor != m_TempACKSendList.end();) {
delete (*itor);
itor = m_TempACKSendList.erase(itor);
}
}
UnlockACK();
}
__except (this->CrashDump(GetExceptionInformation()))

Basically, SEH and C++ unwinding aren't exactly compatible; they require the compiler to modify the function on the machine code level, and MS apparently decided not to support the modifications for the two at the same time, so any function can only support either SEH unwind actions (__except or __finally) or C++ unwind actions (catch or objects with destructors).
I suspect the problem in your case are the iterators in your loops; they might have destructors. Although iterators are usually simple and don't need destructors, this is not the case for debug iterators, which often register their existence on construction and deregister it on destruction, in order to detect invalidated iterators and other invalid usage.
The usual workaround is to split the function. Make your run function contain just this:
void MSocketThread::Run()
{
__try {
RunNoSeh();
} __except (this->CrashDump(GetExceptionInformation())) {
}
}
void MSocketThread::RunNoSeh()
{
// Code that was inside the __try goes here.
}

Related

Exception in Concurrency task.then.wait affects further call of ::ShellExecuteEx()

Following logic is implemented to open a file by a "filename.extension" in a C++ application using managed-C++:
try
{
CoInitialize(nullptr);
auto task = Concurrency::create_task(Windows::Storage::StorageFile::GetFileFromPathAsync(filePath));
// an excpetion is thrown in the next line
Concurrency::task_status status = task.then([&](Windows::Storage::StorageFile^ file){
if (file != nullptr)
{
concurrency::task<bool> launchFileOperation(Windows::System::Launcher::LaunchFileAsync(file));
launchFileOperation.then([&](bool success)
{
if (!success)
return 0;
}).wait();
}
}).wait();
}
catch (...)
{
CoUninitialize(); // an exeption is catched
return 0;
}
Since the above code throws an exception, we go further to an alternative file open approach via ::ShellExecuteEx
SHELLEXECUTEINFO exec_info = {0};
exec_info.cbSize = sizeof exec_info;
exec_info.fMask = SEE_MASK_NOCLOSEPROCESS
| SEE_MASK_DOENVSUBST;
exec_info.fMask &= ~SEE_MASK_NOASYNC;
exec_info.lpVerb = "open";
exec_info.lpFile = full_path_str;
exec_info.nShow = SW_SHOW;
bool result_b = ::ShellExecuteEx(&exec_info) ? true : false;
The ::ShellExecuteEx fails and ends up in Microsofts ppltasks.h
_REPORT_PPLTASK_UNOBSERVED_EXCEPTION();.
::ShellExecuteEx works correctly if the managed-C++ Concurrency::create_task approach is removed.
Why does Concurrency::create_task affect the further call of ::ShellExecuteEx?
This issue appears only in release build.
Adding try/catch-blocks to the innermost .wait()-block solved the issue
try {
concurrency::task<bool> launchFileOperation(Windows::System::Launcher::LaunchFileAsync(file));
launchFileOperation.then([&](bool success) {
// logic
}).wait();
}
catch (concurrency::invalid_operation& ex)
{
...
}
catch (concurrency::task_canceled& ex)
{
...
}

If the application has two services to send data messages, How will the messages be casted in onWSM function to obtain message content?

I tried to cast two messages in the onWSM function, one of the message is the accident message from TraCIDemo11p example see link; https://github.com/sommer/veins/blob/master/src/veins/modules/application/traci/TraCIDemo11p.cc and the other message I created myself.Simulation stops when handling of the accident message begins.
void MyClusterApp::onWSM(BaseFrame1609_4* frame)
{
// Your application has received a data message from another car or RSU
// code for handling the message goes here, see TraciDemo11p.cc for examples
joinMessage* wsm = check_and_cast<joinMessage*>(frame);
if (currentSubscribedServiceId == 7)
{
if(wsm->getRecipientAddress() == myId)
{
mClusterMembers.insert(wsm->getSenderId());
}
}
}
void MyClusterApp::onWSM_B(BaseFrame1609_4* frame)
{
accident* wsm = check_and_cast<accident*>(frame);
if (currentSubscribedServiceId == 8)
{
findHost()->getDisplayString().setTagArg("i", 1, "green");
if (mobility->getRoadId()[0] != ':') traciVehicle->changeRoute(wsm->getDemoData(), 9999);
if (!sentMessage) {
sentMessage = true;
wsm->setSenderAddress(myId);
wsm->setSerial(3);
for( NodeIdSetIterator it = mClusterMembers.begin(); it != mClusterMembers.end(); it++)
{
wsm->setRecipientAddress((*it));
scheduleAt(simTime() + 2 + uniform(0.01, 0.2), wsm->dup());
}
}
}
}
A runtime error occurred:
check_and_cast(): Cannot cast (veins::accident*) to type 'veins::joinMessage *' -- in module (veins::MyClusterApp) VANETScenario.node[1].appl (id=15), at t=74.797089255834s, event #711255
Launch a debugger with the following command?
nemiver --attach=4377 &
It seems that MyClusterApp::onWSM() may handle various types of messages. Therefore, I suggest use dynamic_cast to recognize the type of message - it is safe and returns nullptr when a message cannot be cast.
An example of modification:
void MyClusterApp::onWSM(BaseFrame1609_4* frame) {
joinMessage* wsm = dynamic_cast<joinMessage*>(frame);
if (wsm) {
if (currentSubscribedServiceId == 7) {
if(wsm->getRecipientAddress() == myId) {
mClusterMembers.insert(wsm->getSenderId());
}
}
} else {
// frame is not a pointer to joinMessage
}
}

Unable to work out why a parameter to a method is corrupt in Release mode but OK in Debug mode

Here is a method:
// Override to be notified about every file processed
bool MultiActionsNext(LPCTSTR lpszFileInZip = NULL)
{
if (CZipActionCallback::MultiActionsNext())
{
CMultiActionsInfo* pMulti = GetMultiActionsInfo();
CString strProgress, strPercentComplete;
strPercentComplete.Format(_T("%d%%"),
theApp.CalculatePercent(pMulti->m_uFilesProcessed, pMulti->m_uTotalFilesToProcess));
if (lpszFileInZip != NULL)
{
strProgress = lpszFileInZip;
}
else
{
strProgress.Format(_T("Files Processed: %u of %u"),
pMulti->m_uFilesProcessed, pMulti->m_uTotalFilesToProcess);
}
if (m_pWndProgressText != nullptr)
{
m_pWndProgressText->SetWindowText(strProgress);
m_pWndProgressText->UpdateWindow();
}
if (m_pWndProgressPercentText != nullptr)
{
m_pWndProgressPercentText->SetWindowText(strPercentComplete);
m_pWndProgressPercentText->UpdateWindow();
}
if (m_pProgressCtrl != nullptr)
m_pProgressCtrl->SetPos(pMulti->m_uFilesProcessed);
return true;
}
else
// Processing was requested to be stopped.
// It won't happen in this sample code, because
// the Callback method always returns true.
return false;
}
My problem is with this line of code:
m_pWndProgressText->SetWindowText(strProgress);
If I am in DEBUG mode the result is fine:
But when I am in RELEASE mode the result is garbage:
If I put a break point in this function for lpszFileInZip:
Debug:
Release:
I can't work out why one is OK and one is not.
In Release 32 bit mode I do now notice that I get an exception that indicates the passed in parameter is not valid:

Code runs fine with WinDbg but weird without it

I am debugging an issue with WinDbg which I can consistently produce. The problem is when I run the executable with WinDbg to debug it, the issue can't be reproduced. What could be the reason?
Here is the code the behaves differently:
CWnd* pWnd = GetDlgItem(IDOKCANCEL);
if(pWnd)
{
CString sOK;
sOK.LoadString(IDS_OK);
pWnd->SetWindowText(sOK);
}
Here the button text is updated properly when I run with WinDbg but it is not updated when I run it normally (which is the bug).
Update
Like I said in comments, the issue is not with the code above because it's doesn't even get called. The operation is done in a worker thread which sends update messages to this dialog. The final message that executes the above code is never send do it so the above code is never executed.
Why the worker thread doesn't send this message is interesting. It ges locked on a critical section while opening a database. WinDbg tells me that the main thread is the owner of that critical section but I can't see from call stack or any other way where does it failed to unlock the critical section.
What complicates the problem is that it works fine if I run it with debugger. I added log output but it also starts to works fine with this change.
The only way I can catch it with a debugger is when I run it normal mode, produce the problem, then attach the debugger and it shows me its locked on the critical section. It shows the main thread is the owner of that critical section but it not clear why it is in locked state. The critical section is simply locked and unlocked in one function and its out of there.
Update 2
I am using the critical section only in one file in my entire project and there in only two functions (when it opens database and recordset).
BOOL CADODatabase::Open(LPCTSTR lpstrConnection, LPCTSTR lpstrUserID, LPCTSTR lpstrPassword)
{
CString database = GetSourceDatabase( lpstrConnection, NULL );
// get the appropriate critical section based on database
g_dbCriticalSection = GetDbCriticalSection( database );
if( g_dbCriticalSection)
g_dbCriticalSection->Lock();
HRESULT hr = S_OK;
if(IsOpen())
Close();
if(wcscmp(lpstrConnection, _T("")) != 0)
m_strConnection = lpstrConnection;
ASSERT(!m_strConnection.IsEmpty());
try
{
if(m_nConnectionTimeout != 0)
m_pConnection->PutConnectionTimeout(m_nConnectionTimeout);
hr = m_pConnection->Open(_bstr_t(m_strConnection), _bstr_t(lpstrUserID), _bstr_t(lpstrPassword), NULL);
if( g_dbCriticalSection)
g_dbCriticalSection->Unlock();
return hr == S_OK;
}
catch(_com_error &e)
{
dump_com_error(e);
if( g_dbCriticalSection)
g_dbCriticalSection->Unlock();
return FALSE;
}
}
The 2nd function has other visible imperfections but please ignore that, its legacy code.
BOOL CADORecordset::Open(_ConnectionPtr mpdb, LPCTSTR lpstrExec, int nOption)
{
BSTR bstrConnString;
m_pConnection->get_ConnectionString(&bstrConnString);
CString database = GetSourceDatabase( bstrConnString, m_pConnection );
g_dbCriticalSection = GetDbCriticalSection( database );
if( g_dbCriticalSection)
g_dbCriticalSection->Lock();
Close();
if(wcscmp(lpstrExec, _T("")) != 0)
m_strQuery = lpstrExec;
ASSERT(!m_strQuery.IsEmpty());
if(m_pConnection == NULL)
m_pConnection = mpdb;
m_strQuery.TrimLeft();
BOOL bIsSelect = m_strQuery.Mid(0, _tcslen(_T("Select "))).CompareNoCase(_T("select ")) == 0 && nOption == openUnknown;
int maxRetries = 10;
bool bContinue = true;
CursorTypeEnum adCursorType = adOpenStatic;
if (!m_bSQLEngine)
{
// MDB Engine
adCursorType = adOpenStatic;
m_pConnection->CursorLocation = adUseClient;
}
else
{
// SQL Engine
adCursorType = adOpenDynamic;
m_pConnection->CursorLocation = adUseServer;
}
int currentCommandTimeout = m_pConnection->CommandTimeout;
if( g_dbCriticalSection)
g_dbCriticalSection->Unlock();
for (int iRetry = 0; (iRetry < maxRetries) && bContinue; iRetry++)
{
try
{
// we just use an auto lock object so it is unlocked automatically, it uses same
// critical section object.
if( g_dbCriticalSection)
g_dbCriticalSection->Lock();
int newCommandTimeout = currentCommandTimeout + 15 * iRetry;
m_pConnection->CommandTimeout = newCommandTimeout;
if(bIsSelect || nOption == openQuery || nOption == openUnknown)
{
m_pRecordset->Open((LPCTSTR)m_strQuery, _variant_t((IDispatch*)mpdb, TRUE),
adCursorType, adLockOptimistic, adCmdUnknown);
}
else if(nOption == openTable)
{
m_pRecordset->Open((LPCTSTR)m_strQuery, _variant_t((IDispatch*)mpdb, TRUE),
adOpenDynamic, adLockOptimistic, adCmdTable);
}
else if(nOption == openStoredProc)
{
m_pCmd->ActiveConnection = mpdb;
m_pCmd->CommandText = _bstr_t(m_strQuery);
m_pCmd->CommandType = adCmdStoredProc;
m_pRecordset = m_pCmd->Execute(NULL, NULL, adCmdText);
}
else
{
TRACE( _T("Unknown parameter. %d"), nOption);
if( g_dbCriticalSection)
g_dbCriticalSection->Unlock();
return FALSE;
}
if( g_dbCriticalSection)
g_dbCriticalSection->Unlock();
bContinue = false;
}
catch(_com_error &e)
{
if( g_dbCriticalSection)
g_dbCriticalSection->Unlock();
dump_com_error_without_exception(e, _T("Open"));
// retry Query timeout
CString szDescription;
_bstr_t bstrDescription(e.Description());
szDescription.Format( _T("%s"), (LPCTSTR)bstrDescription);
if ((szDescription.Find(_T("Query timeout expired")) == -1) || (iRetry == maxRetries - 1))
{
m_pConnection->CommandTimeout = currentCommandTimeout;
throw CADOException(e.Error(), e.Description());
}
Sleep (1000);
bContinue = true;
}
}
m_pConnection->CommandTimeout = currentCommandTimeout;
return m_pRecordset != NULL && m_pRecordset->GetState()!= adStateClosed;
}
For the sake of completeness, the above calls this function:
static CCriticalSection* GetDbCriticalSection(const CString& database)
{
// For now we only care about one database and its corresponding critical section
if (database.CompareNoCase( _T("Alr") ) == 0)
return &g_csAlrDb; // g_csAlrDb is defined static global in this file
else
return 0;
}
The Open() function gets called for various databases, I am only locking guarding access to one database. As you can see there is corresponding lock/unlocks so not sure how does code comes up of these functions leave th critical section locked. Could it be because of MFC issue?
In my case, most of the time, when C++ software behaves different between debug and release versions, it's because of uninitialized variables, different libraries linked, or compiler optimizations backfiring.
To trace the bug, try evaluating variables and function return values, i.e. LoadString, for example with AfxMessageBox().

LinearHashTable iter not dereferencable and iter not

Hy all :)
I am using 1.5.4-all (2014-10-22) in my VC++ project (Microsoft Visual C++ Compiler 18.00.21005.1 for x86 platform).
My problem is that I get the following error message after some time. The time, after which the error occurs differ quiet a lot - sometimes it happens after 30 secs and sometimes after 5 minutes.
I could locate the source for the error in the LinearHashTable.h file at line 214:
I have the following method where a Shot (struct) is added to the table:
void ShotSimulationService::SimulateShot(Shot shot) {
MutexThreadLock.lock();
shots.insert(ShotsSetType::ValueType(SimulationShot(shot)));
errorCount = 0;
MutexThreadLock.unlock();
}
The call of SimulateShot is from another thread than the handling of the following code:
void ShotSimulationService::Update(WebcamService* observable) {
if (shots.empty()) {
return;
}
try {
Mat frame = observable->GetLastImage().clone();
ShotsSetType::Iterator iter = shots.begin();
vector<Shot> deleteShots;
errorCount++;
while (iter != shots.end()){
if (iter->SimulateStartExplosion()) {
//simulate gun explosion
OverlayImage(frame, gunShotImg, iter->startPoint);
}
//simulate explosion
SimulationShot::SimulationHitStatus status = iter->status;
if (status == SimulationShot::SimulationHitStatus::UNKNOWN) {
if (detectionService.HasShotHitPlayer(frame, *iter)) {
iter->status = SimulationShot::HIT_PLAYER;
iter->SetCurrentPointAsEndoint();
//Notify that player was hit
playerHitQueue.enqueueNotification(new PlayerHitNotification(iter->hitPlayer));
}
}
if (iter->SimulateEndExplosion()) {
if (status == SimulationShot::HIT_PLAYER) {
int explosionx = iter->endPoint.x - robotExplosionHalfXSize > 0 ? iter->endPoint.x - robotExplosionHalfXSize : 0;
int explosionY = iter->endPoint.y - robotExplosionHalfYSize > 0 ? iter->endPoint.y - robotExplosionHalfYSize : 0;
OverlayImage(frame, robotExplosionImg, Point2i(explosionx, explosionY));
}
else {
// status == SimulationShot::HIT_WALL or UNKNOWN
int explosionx = iter->endPoint.x - wallExplosionHalfXSize > 0 ? iter->endPoint.x - wallExplosionHalfXSize : 0;
int explosionY = iter->endPoint.y - wallExplosionHalfYSize > 0 ? iter->endPoint.y - wallExplosionHalfYSize : 0;
OverlayImage(frame, robotExplosionImg, Point2i(explosionx, explosionY));
if (status != SimulationShot::HIT_WALL) {
iter->status = SimulationShot::HIT_WALL;
}
}
if (iter->IsSimulationFinished()) {
deleteShots.push_back(*iter);
}
}
else {
//simulate bullet
OverlayImage(frame, cheeseImg, iter->GetNextShotPoint());
}
++iter;
}
//delete finished simulations
MutexThreadLock.lock();
for each (Shot shot in deleteShots)
{
shots.erase(shot);
}
MutexThreadLock.unlock();
}
catch (cv::Exception& e) {
Logger& logger = Logger::get("Test");
logger.error(e.what());
}
}
The Update method is called quiet often - always when a new webcam frame is available.
The callstack of the error starts in the following line:
if (iter->SimulateEndExplosion()) {
In the method SimulateEndExplosion only members of the struct were used:
bool SimulateEndExplosion() {
if (status == HIT_PLAYER) {
currPercentage = 1.0;
return true;
}
if (currPercentage < 1.0) {
return false;
}
++endExplosionCtr;
return endExplosionCtr <= maxEndExplosions;
}
Does anybody have an idea why this problem occurs?
Any help and any feedback is welcome!! I have absolutly no idea what is going wrong here :(
Thanks!
Iterating in one thread and inserting in another without protecting the operations with mutex in both threads will cause this problem; when you insert, iterator will be invalidated and you will get the assertion failure. You should protect both insertion and iteration with mutex.
Also, the way you are using mutex is not safe because mutex will not be unlocked if an exception is thrown between lock() and unlock(). Use ScopedLock instead and RAII will do the job automatically and safely in all cases:
void ShotSimulationService::SimulateShot(Shot shot) {
Mutex::ScopedLock lock(MutexThreadLock);
shots.insert(ShotsSetType::ValueType(SimulationShot(shot)));
errorCount = 0;
// unlock will be called by ScopedLock destructor
}