rulururu

post Don’t use void for functions without arguments

August 4th, 2008

Filed under: C++ — Kai @ 2:50 pm

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.

post CompareNoCase does not work as expected

July 30th, 2008

Filed under: C++, MFC — Kai @ 11:18 am

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);
}

post Single Instance managed by GUID

July 22nd, 2008

Filed under: C++ — Kai @ 3:29 pm

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.

post Google Open Sources C++ Testing Framework

July 15th, 2008

Filed under: C++, General Programming, Internet, Software — Kai @ 3:22 pm

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

post Deleting objects in the heap with wxWidgets

June 26th, 2008

Filed under: C++ — Kai @ 8:33 pm

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.

post Do not step into trivial functions

June 26th, 2008

Filed under: C++, Visual Studio — Kai @ 11:00 am

Today I’d like to explain to you how you can prevent the debugger from stepping into trivial functions. In my examples I use wxWidgets and its wxString. It should be almost the same if you use MFC and its CStrings.

If you do a lot of debugging (and who doesn’t?), you’ve probably encountered many function calls that you’d really like to step into. In particular, if the code makes function calls to produce arguments for the function:

call_me( new foo( "a", 1 ), my_vector.begin(), my_vector.end() );

When you are single stepping in the debugger (using F11) and you want to step into a function that has strings as a parameter, the debugger will first step into the string constructor. This is correct but annoying - especially when you are absolutely certain that you don’t need to. You don’t want to debug the string constructor. The same applies to many other functions, e.g. new(), malloc(), wxString::c_str(). There is a way to tell the debugger to step over these functions even if you use “Step Into”.

Create a ‘NoStepInto’ entry for every function you do not want to step into.

Note: Visual Studio uses the regular expression syntax to specify the function names. regexp is much more powerful than wildcards such as ? and *.

Note: Don’t forget - you have to “escape” special characters with ‘\’. If you want to step over wxString::c_str*, you need to write wxString\:\:c_str.*. There is a lot of confusion in the newgroups and other examples if you need to write \\:\\: or simply \:\:.. My personal view is, \: is enough (as is correct with regexp) and the other expression came from pasting a CString to a newgroup post.

If you are using Visual Studio 6, add these lines to autoexp.dat under

[ExecutionControl]
wxString\:\:c_str.*=NoStepInto
operator new=NoStepInto

If you are using Visual Studio .NET 2003 or 2002, modify the registry.

  • Add the Key NativeDE\StepOver under HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\7.1 (or 7.0 if you are using .NET 2002)
  • For every function you want to skip, add a new key/string value under the StepOver key.
  • The keys must be numerical. Think of them as linenumbers like in the old Basic days. Due to a bug in the Debugger, these numbers will get evaluated in reverse order.
  • The string contains the regular expression I have described above.

For instance, this is a good idea:

HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\7.1\NativeDE\StepOver\10 = wxString\:\:c_str.*

This will prevent the debugger from stepping into these functions when you press F11 or choose “step into”.
Other useful expressions are:

  • wxString Constructor
  • wxString\:\:wxString
  • wxString Destructor
  • wxString\:\:~wxString

Visual Studio 8 has the same basic functionality as Visual Studio 7 with a few improvements. In addition, you should be aware that the key you must modify is now:

HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\8.0\NativeDE\StepOver

You’ll need an account with Admin privileges to set this up.

In addition to the ability to match regular expressions provided in Visual Studio 7, a few new escape sequences have been added to the regular expressions you can use, including '\funct' to match the name of a function, '\scope' to match a scope (e.g., std::my_namespace::etc::so::forth), and '\oper', which matches any operator.

Note: When using these escape sequences, you must indicate the end of the escape sequence with a colon. So you might write '\scope:' followed by the rest of the expression to match.

For example, you could avoid stepping into any overloaded operators by using the expression

\scope:operator\oper:=NoStepInto

which might be useful if you are using a lot of classes with simple operators whose behaviors you can trust to be correct.

There is a lot more you can do with it. Once done it saves time and energy ;)

ruldrurd
« Previous PageNext Page »
Powered by WordPress, Content and Design by Kai Bellmann
Entries (RSS) and Comments (RSS)