|
I did a very lengthy evaluation of static analysis tools at my last job. In summary, cppcheck is pretty good and since it's free, why not. Of the paid tools, PVS-Studio was one of the best and very reasonably priced (not any more!) and rather expensive, but not as much as other tools (Unfortunately, instead of just listing a price, they play games with you, which means I really can't recommend them anymore--any company too chickenshit to put up plain prices doesn't deserve my business.) Of the super-expensive tools, the best, by a huge margin, was Coverity. It found almost all of the known issues, several critical issues none of the other tools found and almost three dozen minor issues. They are expensive, but worlds better than Klocwork and Parasoft.
Parasoft was pretty bad--their analysis tool did better than Klocwork, but missed several issues cppcheck caught and missed several known critical errors. Their product is excruciating slow and Parasoft's other tools were a disaster--several wouldn't even run. Klocwork was very buggy, missed several known bugs and their support was offensively useless (the evaluation went so badly that we terminated it early.)
One thing I concluded is that Parasoft and Klocwork specialize in selling to companies which must comply with weird rules for government work (for which there are hundreds of rules, like how switch statements must operate.) They do well at that, but not so well in finding actual bugs.
(Riverblade Software which makes Visual Lint, a tool which helps you deal with PC-Lint and Cppcheck--I don't much like it, but you may.)
modified 22-Nov-13 13:00pm.
|
|
|
|
|
Interesting you mentioned Parasoft: a couple of years ago (at a time when it was still relatively cheap) I chose it over lots of others based on a comparison report (which I unfortunately cannot locate any more). Back then it was indicated to be one of the best tools available for the Windows platform (the best affordable one at least), and indeed we got very good results.
That said, like what you stated about PVS, they don't openly state their prices, and now they're much more expensive than they used to be. Unfortunately this seems to be common practice for software tool makers nowadays Good thing there is open source! But still a pain when you really need to find the best tool for the job and end up wasting hours with inquiries only to find out the price tags are way beyond sanity!
Note however that Parasoft does instrument code for runtime analysis too, and we could uncover a number of very nasty memory leaks and bugs that we wouldn't have found in years without a tool, and not at all with static analysis alone! It's true they're not really great at static analysis, but that was never our main concern to start with!
GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)
|
|
|
|
|
Re: Parasoft runtime analysis. This is one of the modules that failed during our evaluation. I can see how it used to be good, but it hasn't kept up with BoundsChecker. When I finally did get the runtime analysis to work, it presented two false positives!
One thing that really struck me during the evaluations is how poorly much of the software was written, especially for such expensive products. The number of obvious UI bugs in Klocwork were astounding (like toolbar buttons simply not working.) Klocwork and Parasoft both failed during installation! This is software which costs hundreds of thousands of dollars and the installer doesn't even work!
|
|
|
|
|
In normal situations, the following code stops timer as expected:
CreateWaitableTimer...
SetWaitabltTimer... // with duration 0 and period USER_TIMER_MINIMUM
CancelWaitableTimer...
Here, I mean 'normal' as 'not using socket calls'.
However, when the two conditions are met, CancelWaitableTimer does not stop timer. I've tried to find out why, in vain. The two conditions are:
- CSocket::Connect or CAsyncSocket::Connect was called
- the last SetWaitableTimer was called with Duration 0 and period USER_TIMER_MINUMUM
Actually USER_TIMER_MINUMUM is only to repeat the issue everytime in 100%.
If period is long enough, this issue happens irregularly.
That is, the following code fails to stop the timer.
CreateWaitableTimer...
SetWaitabltTimer... // with duration 0 and period USER_TIMER_MINIMUM
CSocket::Connect... // use Connect from CSocket or CAsyncSocket
CancelWaitableTimer...
Since it is too hard to post a complete source code here,
I would email the zipped project file if you send me an email to 'ehaerim at gmail dot com'.
thx
HaeRim Lee
modified 17-Nov-13 21:40pm.
|
|
|
|
|
First of all, what do you mean when you say "fails to stop the timer"? Does CancelWaitableTimer return an error, or does the execution stop at CSocket::Connect ? Details, please.
(Also, it helps if you use the formatting options when posting, to separate text from code.)
Have you tried using Windows sockets directly? The MFC socket classes are very poorly implemented (see here[] for more details), and it's generally not that much more work to write your own. (Hm. Maybe I ought to dig out the implementation I wrote that I own and write it up as an article.)
|
|
|
|
|
> Orjan Westin wrote:
> First of all, what do you mean when you say "fails to stop the timer"?
> Does CancelWaitableTimer return an error, or does the execution stop at CSocket::Connect?
> Details, please.
CancelWaitableTimer(CWT) returns TRUE, but fails to stop the timer activated by SetWaitableTimer(SWT).
You can download the complete source code from ftp://ftp1.investware.net:1250/Temp/WT3.zip
Compiling and running the sample should NEVER raise an ASSERT if CWT works correctly, that is, CWT returning TRUE MUST stop the timer activated by the last SWT.
WTDlg.cpp lines 14-17 show some #define statements.
[1] First simple test case in which no socket is used and CWT returning TRUE works as expected and succeeds in stoping the timer
#define WAITABLETIMER_PERIOD (USER_TIMER_MINIMUM * 1)
#define WAITABLETIMER_DUETIME_INITIALLY (0)
[2] Second abnormal test case in which socket is used and CWT returns TRUE, but fails to stop the timer, and therefore ASSERT is triggered.
#define WAITABLETIMER_PERIOD (USER_TIMER_MINIMUM * 1)
#define WAITABLETIMER_DUETIME_INITIALLY (0)
#define TEST_WITH_SOCKET
[3] You can test a variety of cases by modifying the first two #define statements. The most significant factor is the value of 'WAITABLETIMER_PERIDO'.
When it is
- USER_TIMER_MINIMUM * 1, ASSERT is triggered 100%.
- ~ USER_TIMER_MINIMUM * 50, ASSERT is triggered 100% as far as I tested.
- USER_TIMER_MINIMUM * 75, ASSERT is triggered 1~2 times out of 5 executions.
- USER_TIMER_MINIMUM * 100, ASSERT is triggered 1~2 times out of 10 executions.
The less significant but still affecting the result is the value of 'WAITABLETIMER_DUETIME_INITIALLY'.
When it is -1, much lower possibility of ASSERT.
Now, I believe you have all that you can play around.
In conclusion, all I can say is that CWT returning TRUE does not stop the timer immediately, but after the timer is signaled one more time for the following sequences:
- SetWaitableTimer is called with Duration 0 and period USER_TIMER_MINIMUM
- CSocket::Connect or CAsyncSocket::Connect is called
- CancelWaitableTimer is called
If you find out why CWT returning TRUE fails to stop the timer, please let me know.
thx
modified 20-Nov-13 5:43am.
|
|
|
|
|
Hi,
I looked over your code. The behavior is exactly as documented:
CancelWaitableTimer function[^]
The CancelWaitableTimer function does not change the signaled state of the timer. It stops the timer before it can be set to the signaled state and cancels outstanding APCs. Therefore, threads performing a wait operation on the timer remain waiting until they time out or the timer is reactivated and its state is set to signaled. If the timer is already in the signaled state, it remains in that state.
Your due time is set to the minimum 0xA value (one NT quantum). By the time you have called CancelWaitableTimer[^]... the timer is already in the signaled state.
If you want to reset a timer that is already in the signaled state... call the SetWaitableTimer function[^] to manually reset the timer to the non-signaled state and then call the CancelWaitableTimer function[^].
In other words... the code within your
#if defined(TEMP_WORKAROUND) is correct way to cancel the timer.
Best Wishes,
-David Delaune
|
|
|
|
|
David,
First of all thx for your kind response.
But, I think you have read the code a bit wrong way withing the limit of my knowledge.
Randor wrote: Your due time is set to the minimum 0xA value (one NT quantum).
This is wrong because I set the initial due time and period as follows at line 15-16
#define WAITABLETIMER_PERIOD (USER_TIMER_MINIMUM * 1)
#define WAITABLETIMER_DUETIME_INITIALLY (0)
It is the period that set to 0xA, not the initial due time.
The initial due time and period is intentionally set to 0 and 0xA to fire the timer 'immediately first time and ,after then, in the period of every 0xA milliseconds'.
Because of 'immediate due time', the timer gets signaled 'immediately' literally, and therefore 'case WAIT_OBJECT_0 + 1:' statement is the first statement executed without any delay.
Then socket Connect fails with WSAEWOULDBLOCK error and finally CWT call returns TRUE in sequence.
So, the overall code flow is like this:
pWTDlg->m_hTimerRC = CreateWaitableTimer(NULL, FALSE, NULL);
bRet = SetWaitableTimer(pWTDlg->m_hTimerRC, 0, 0xA, NULL, NULL, NULL);
pWTDlg->m_bCreated = sock.Create();
pWTDlg->m_bConnected = sock.Connect(...);
bRet = CancelWaitableTimer(pWTDlg->m_hTimerRC);
Since the last CancelWaitableTimer returns TRUE, it should stop the timer right away, but the timer gets signaled just one more time. That's the issue!
Questions here are
- Why is the timer not stopped even after CWT returns TRUE?
- Why is the timer always signaled just one more time, not two or three and so on even if I admit the timer can be signaled more times after CWT returns TRUE(of course, I don't admit this, but just for the discussion of this issue, though)?
- What's the use of CWT if it is not guaranteed to stop the timer immediately? I'd rather set INFINITE due time and/or INFINITE period for SWT instead of using CWT.
I hope I miss something but unfortunately I don't know what are they.
Please be very specific and detail explaining what's going on about this issue.
regards
|
|
|
|
|
Hi,
Yes, by setting the initial due time to zero the waitable timer becomes immediately signaled. When the timer becomes signaled an APC is queued on your thread. When an APC is queued on your thread the kernel object representing the timer object has its reference count incremented. When you call CancelWaitableTimer if an APC is queued on your thread... a single APC is dequeued and the reference count is decremented by one and the timer is NOT cancelled.
Follow the instructions in my previous post to cancel your waitable timer.
Other thoughts... You can achieve the one-time timer fire by simply setting the
_In_ LONG lPeriod, argument to zero.
Best Wishes,
-David Delaune (MSFT)
|
|
|
|
|
Can you clearly explain why the code below triggers the timer twice from time to time, say once in 5-10 executions?
MSDN does not explain this weird phenomenon at all.
#if !defined(BTF)
#define BTF(b) (b ? _T('T') : _T('F'))
#endif
#if !defined(ERR)
#define ERR(b, d) (b ? 0 : d)
#endif
BOOL CWTApp::InitInstance()
{
CWinApp::InitInstance();
HANDLE hTimer = CreateWaitableTimer( NULL, FALSE, NULL );
BOOL bRet;
DWORD dwErr;
#define WAITABLETIMER_DUETIME_INITIALLY (0)
#define WAITABLETIMER_PERIOD (USER_TIMER_MINIMUM * 200)
#define SLEEP_BEFORE_CWT Sleep(50)
LARGE_INTEGER DueTime;
DueTime.QuadPart = WAITABLETIMER_DUETIME_INITIALLY;
bRet = SetWaitableTimer(hTimer, &DueTime, WAITABLETIMER_PERIOD, NULL, NULL, FALSE);
ATLTRACE(_T("SetWaitableTimer_1(hTimer)=%c/%d\n"), BTF(bRet), ERR(bRet, GetLastError()));
dwErr = WaitForSingleObject(hTimer, INFINITE);
ATLTRACE(_T("Timer(1) was signaled. dwErr=%d\n"), dwErr);
SLEEP_BEFORE_CWT;
bRet = CancelWaitableTimer(hTimer);
ATLTRACE(_T("CancelWaitableTimer(hTimer)=%c\n"), BTF(bRet), ERR(bRet, GetLastError()));
dwErr = WaitForSingleObject(hTimer, INFINITE);
ATLTRACE(_T("Timer(2) was signaled. dwErr=%d\n"), dwErr);
bRet = CloseHandle(hTimer);
return FALSE;
}
modified 23-Nov-13 14:27pm.
|
|
|
|
|
I am trying to extract the functions in a module by using the DBGHELP.LIB functions and loading only the PDB.
I can't seem to get SymEnumSymbols to invoke the callback at all. The SymEnumSymbols function returns 'success' as if it had done something. Trying various combinations of 'options' using SymSetOptions has not yielded results either. When I search The Internet almost always the result/examples seem to come back with examples where the EXE is loaded and running and has been attached to or at very least the process handle has been obtained.
Is having the process handle of the running EXE a requirement Microsoft has completely forgotten to state while using this 'Debug' library?
Thanks.
I need a 32 bit unsigned value just to hold the number of coding WTF I see in a day …
|
|
|
|
|
|
I had few CBitmapButton(s) on a CDIalogBar, but I had noticed that they are not react on Enter key, only on mouse click ? How can I workaround in order to react on enter key ? Thank you.
|
|
|
|
|
Where is the focus when you press the enter key?
Veni, vidi, abiit domum
|
|
|
|
|
On the CBitmapButton, of course
|
|
|
|
|
I know what you are trying to say, that the focus is stealing by CMainFrame, but I must say that CBitmapButton react on "SPACE" key, so that is the prove that the button had th focus ...
|
|
|
|
|
Flaviu2 wrote: I know what you are trying to say Actually, I was not trying to say anything, merely asking the obvious question. I had a good root through the documentation for this control and cannot find anything in MSDN that explains what is supposed to happen. I know that in a normal dialog it will work this way, but I don't have MFC so cannot make a sample to test what you are trying to do.
Veni, vidi, abiit domum
|
|
|
|
|
Ok, I understand. Thank you for your concern.
|
|
|
|
|
hi all,
I am get window text like this in my function it works fine for multibyte data but fails in case of Unicode data.
HWND hWnd;
char string [256]={_T('\0')};
::SendMessage(hWnd, WM_GETTEXT, 255, (LPARAM)string);
and
TCHAR szBuffer[MAX_PATH] = {_T('\0')};
SendMessage(hWnd, WM_GETTEXT, sizeof(szBuffer) / sizeof(TCHAR), (LPARAM)szBuffer);
please help me to get the Unicode data.
thank in advance.
|
|
|
|
|
I have used the same code as you have above to receive the Unicode text from a window. Are you sure you set the project options to select a UNICODE build?
Veni, vidi, abiit domum
modified 15-Nov-13 9:02am.
|
|
|
|
|
|
Hi all,
I am getting a weird stack overflow after calling the MFC function SetLocalTime. There is no code to step into and no call stack. I am using Visual Studio 2008 on Windows CE.
Here is my code:
void OnBnClickedButtonSet()
{
SYSTEMTIME time, new_time;
GetLocalTime(&time);
//get the date info
time.wYear = static_cast<WORD>(i_year);
time.wMonth = static_cast<WORD>(i_month);
time.wDay = static_cast<WORD>(i_day);
//get the time info
DWORD ret = m_Time.GetTime(&new_time);
if (ret == GDT_VALID)
{
time.wHour = new_time.wHour;
time.wMinute = new_time.wMinute;
time.wSecond = new_time.wSecond;
time.wMilliseconds = 0;
}
else
{
TRACE(_T("not a time format\n"));
return;
}
CString str(_T(""));
//set the date and time
if (!SetLocalTime(&time))
{
str.Format(_T("system time error = %d. \n"), GetLastError());
TRACE(str);
return;
}//here the stack overflow message shows up; it only happens the first time i turn the unit on and if the user chooses new values only for the date (no stack overflow when setting the time).
}
SetLocalTime doesn't return an error and sets the chosen values for date/time, even if WindowsCE crashes and it needs restarting. After restarting, the date and time can be set again without any problems...
The Disassembly Window points here: "40060198 stmdb sp!, {r0, r4, r5, lr}". I don't know if this is helpful or not...
I tried SecureZeroMemory(&time, sizeof(time)) before GetLocalTime(&time) but no change.
Thanks in advance for your help.
CB
modified 14-Nov-13 10:34am.
|
|
|
|
|
Sounds like a possible recursion issue. What happens if you comment out the call to SetLocalTime() ?
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Show me a community that obeys the Ten Commandments and I'll show you a less crowded prison system." - Anonymous
modified 14-Nov-13 15:17pm.
|
|
|
|
|
The stack overflow message doesn't appear but the new date doesn't get set.
CB
|
|
|
|
|
After SetLocalTime() is called, how many times does OnBnClickedButtonSet() get called?
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Show me a community that obeys the Ten Commandments and I'll show you a less crowded prison system." - Anonymous
|
|
|
|
|