September 19th, 2008
NULL in c is defined as (void*)0, While for C++ its simple 0. Any ideas ?
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
As you know C++ is a direct descendant of C that retains almost all of C as a subset. Maybe it’s because of the fact that C++ provides stronger type checking than C and directly supports a wider range of programming styles than C.
Obviously it’s not that important because well written C tends to be legal C++ also.
August 4th, 2008
In ANSI C, void Foo() takes an arbitrary number of arbitrarily typed arguments (although the form void Foo(...) is preferred) and void Foo(void) doesn’t take any arguments. In C++, however, the situation is different and both declarations are completely equivalent. As there is no need to write void in this situation, let’s not write it — it can only be confusing and create an impression that it really means something when it’s not at all the case.
July 30th, 2008
Recently I found a program of mine doing all kind of unexpected things because of CString::CompareNoCase() not returning what I expected it to return.
My application usered names containing the characters: é, è, à. Somewhere in my app I used the given name to search the corresponding object in a list. Since the given names had to be (case insensitive) unique I stored those names in uppercase format.
Afterwards I compared (in a case insensitive way) the given name with the uppercase name of each object in the list.
And that went unexpectedly wrong! Look at the following code snippet:
CString strText("élève - à la façon - château");
CString strTextUpper(strText);
strTextUpper.MakeUpper(); // Upper case the original
int match = strTextUpper.CompareNoCase(strText); //does not match
For CString::CompareNoCase I read:
Compares this CString object with another string using the generic-text function _tcsicmp. The generic-text function _tcsicmp, which is defined in TCHAR.H, maps to either _stricmp, _wcsicmp, _mbsicmp depending on the character set that is defined at compile time. Each of these functions performs a case-insensitive comparison of the strings, and is not affected by locale.
While digging deeper in MSDN I discovered the existence of CString::CollateNoCase for which I read:
Compares this CString object with another string using the generic-text function _tcscoll. The generic-text function _tcscoll, which is defined in TCHAR.H, maps to either stricoll, wcsicoll, or _mbsicoll depending on the character set that is defined at compile time. Each of these functions performs a case-insensitive comparison of the strings, according to the code page currently in use.
This knowledge led me to two workarounds:
- Use
CString::CollateNoCase instead of CompareNoCase.
- Although the help says it works independent of the locale, before calling
CString::CompareNoCase set (the LC_CTYPE part of the) the locale. e.g.:
setlocale(LC_CTYPE, "french-belgian");
Finally my confidence in MFC’s CString comparison functions isn’t great after I discovered this. And that’s why I wrote my own ever-working workaround:
int MyCompareNoCase(LPCTSTR str1, LPCTSTR str2)
{
CString strTmp1(str1);
CString strTmp2(str2);
strTmp1.MakeUpper();
strTmp2.MakeUpper();
return strTmp1.Compare(strTmp2);
}
July 22nd, 2008
Some of the applications need to be restricted to run as a single instance. This can be achieved very easily in C++ applications.
When the application is started, it has to be checked if there is another instance running. If there is one already running, a message should be displayed and the application quit from the environment.
By default MFC provide no APIs or methods to satisfy this. But, by using mutex, the work is so simple.
For this we need a GUID (Globally Unique Identifier). You can create this by using the MFC application
A small tool called guidgen.exe generates a GUID.
First of all you have to start guidgen.exe. All you have to do is to click the New GUID button in the Create GUID dialog box.
After that you need to create a named mutex semaphore when you start your application. When the second one starts it tries to get access to the mutex but will fail…
Implement one method:
BOOL CThreadTestApp::SingleTest (LPSTR szName)
{
HANDLE hMutex = CreateMutex (NULL, TRUE, szName);
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
CloseHandle(hMutex);
return FALSE;
}
return TRUE;
}
Call the method in InitInstance() like:
if (SingleTest (_T("SingleTest_48C56927-A0DB-4e31-8C32-FE15FBA45043")))
{
}
else
{
AfxMessageBox(_T("Error: application is already running!"));
return FALSE;
}
This check is performed inside the CWinApp derived classes in MFC. The CWinApp::InitInstance function is the ideal place for performing such initial check-ups.
July 15th, 2008
The Google C++ Testing Framework known also as Google Test, based on xUnit has been used by many of the Google C++ developers to help in unit testing their C++ applications. It is portable and works on Linux, Windows, Mac etc with GCC and MSVC compilers and even embedded systems. You can even use it to kill your Linux applications so that they die as you expect them to. Or have it continue testing after non-fatal errors. Now they have made it available as an open source library.
Google doesn’t claim that their test framework is better than others but they have made it easy to extend it by adding new test macros. You can read more in the primer and faq.
Link: Google C++ Testing Framework
June 26th, 2008
For private use I often prefer wxWidgets to MFC, even thougth there’s no wide difference except of that wxWidgets runs on almost every platform.
I recently noticed that wxWidgets offers two nice macros wxDELETE and wxDELETEA, which you definitly should prefer using when deleting objects:
#define wxDELETE(p) if ( (p) != NULL ) { delete p; p = NULL; }
#define wxDELETEA(p) if ( (p) ) { delete [] (p); p = NULL; }
It deletes pointer if it is not NULL and NULL it afterwards.
It’s not really a smart innovation, but as so many things it saves time and brain cells. According to my opinion it can be regarded as useful when detecting memory leaks because you can easily search your code for those macros.