rulururu

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

post Force all non-zero values to 1

June 20th, 2008

Filed under: C++ — Kai @ 11:56 am

Let’s assume that you want to set all non-zero values to 1.
Usually, I’d prefer the simple and understandable way:

if(a != 0)
   a = 1;

or

a = (a==0) ? a : 1;

I found out a cool trick that I didn’t want to keep back from you:

a = !!a;

Funny, but too adventurous to use it in real life ;)

post Starting an application minimized without flickering

June 20th, 2008

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

To start an application minimized (e.g. appearing directly in the tray area), the common way to do this is calling ShowWindow(SW_HIDE) as soon as possible, preferably directly after the call to CDialog::OnInitDialog().

This surely does the trick, but every now and then, you will see your main dialog window flickering for a fraction of a second before it is finally hidden or sent to the tray area.

This is because the basic window has already been created when CDialog::OnInitDialog() returns, and its default behaviour is to appear on screen (in fact, this is what windows were made for).

Maybe in a few years, when computers operate much more faster than they do now, you’ll get rid of this annoying flickering automatically, because your Operating System will then hide your window before you even start the corresponding application.

But for now, just add this OnWindowPosChanging() handler to your application:

void CTestDlg::OnWindowPosChanging(WINDOWPOS* lpwndpos) 
{
    if(m_bDlgVisible == false)
        lpwndpos->flags &= ~SWP_SHOWWINDOW;
 
    CDialog::OnWindowPosChanging(lpwndpos);
}

You can also declare an optional boolean member variable (m_bDlgVisible in this example), which is initialized to true in the constructor and gets toggled in the corresponding SendToTray() and RestoreFromTray() functions. This way, I can track the current window state (IsWindowVisible() would also work) for different purposes.

post Comma Operator

June 17th, 2008

Filed under: C++ — Kai @ 10:23 am

A colleague of mine reported an error in the program flow. The line that was wrong looked like this (variable and class names are modified):

if(pCurrent->m_Array[r]->Match(((CMyClass*)this)->m_ptrAttr[i])), (CMyClass*)this)

We soon noticed that the number of braces in that statement is wrong. The ) before the comma closes the statement wrongly. Just a mistake you make when writing statement without paying attention.

Fix simply looked like this:

if(pCurrent->m_Array[r]->Match(((CMyClass*)this)->m_ptrAttr[i]), (CMyClass*)this)

The strange thing about it is that the compiler didn’t even throw a warning that we used a comma in that if statement. The comma operator seemed to be valid usage in C++ if statements.

I quickly looked it up and found out that the binary comma operator is almost only ever used for its side effects, as all it does is to ignore the value on its left and return the value on its right so.

that means

if( 0 , 1 )

always returns true because just the right side is considered.

I at first thought “Huh - that’s useless, what nonsense!” - but then I kept on reading what’s its second usage:

Its common usages is to sneak extra initialisation into a for’s loop init-expr e.g.:-

for ( i=0, j=0; ...

init-expr is an example of an expression whose value is not used, its only the side effect (initialisation) that matters.

Although this is definitely worse coding style you can use commas for the side effect if you want to. ;)

post Too circuitous for a Macro?

June 5th, 2008

Filed under: C++, Nonsense — Kai @ 5:43 pm

Let’s imagine you need a make some letter’s uppercase. I would usually use the build in CString function or too make it very simple something like this:

string toupper(const string& str)
{
   string s = str;
   int len = s.length();
 
   for(int i = 0; i < len; i++)
       if( s[i] >= 'a' && s[i] <= 'z' )
           s[i] -= 32;
 
   return s;
}

or if I wanted to stuck more to C-style:

for ( int a = 0; a < strlen ( mystring ); a++ )
   if ( mystring [ a ] >= 'a' && mystring [ a ] <= 'z' )
       mystring [ a ] &= 0xdf;

Some people prefer using macros for short operations.
The advantage of a macro is that it can be type-neutral (this can also be a disadvantage, of course), and it’s inlined directly into the code, so there isn’t any function call overhead. (Note that in C++, it’s possible to get around both of these issues with templated functions and the inline keyword.)

In C++, you should generally avoid macros when possible. You won’t be able to avoid them entirely if you need the ability to paste tokens together, but with templated classes and type inference for templated functions, you shouldn’t need to use macros to create type-neutral code.

Another reason the prevent usage is that debugging a macro is not that comfortable…
Nevertheless a correct macro would be:

#define TO_UPPER(c)  ( ((c)>='a'&&(c)<='z') ? ((c)-'a'+'A') : (c) )

It’s short, readable and particularly reuseable.

Now we come to the piece of code I really wanted to get at. I found it yesterday night in a project I don’t want to embarrass in public (No, I DIDN’T find it at work!):

// Macro to normalize table names
// (all of them will be stored in upper case )
#define TO_UPPER( x )(         \
     ( 'a' == ( x ) ) ? 'A' :        \
     ( 'b' == ( x ) ) ? 'B' :        \
     ( 'c' == ( x ) ) ? 'C' :        \
     ( 'd' == ( x ) ) ? 'D' :        \
     ( 'e' == ( x ) ) ? 'E' :        \
     ( 'f' == ( x ) ) ? 'F' :        \
     ( 'g' == ( x ) ) ? 'G' :        \
     ( 'h' == ( x ) ) ? 'H' :        \
     ( 'i' == ( x ) ) ? 'I' :        \
     ( 'j' == ( x ) ) ? 'J' :        \
     ( 'k' == ( x ) ) ? 'K' :        \
     ( 'l' == ( x ) ) ? 'L' :        \
     ( 'm' == ( x ) ) ? 'M' :        \
     ( 'n' == ( x ) ) ? 'N' :        \
     ( 'o' == ( x ) ) ? 'O' :        \
     ( 'p' == ( x ) ) ? 'P' :        \
     ( 'q' == ( x ) ) ? 'Q' :        \
     ( 'r' == ( x ) ) ? 'R' :        \
     ( 's' == ( x ) ) ? 'S' :        \
     ( 't' == ( x ) ) ? 'T' :        \
     ( 'u' == ( x ) ) ? 'U' :        \
     ( 'v' == ( x ) ) ? 'V' :        \
     ( 'w' == ( x ) ) ? 'W' :        \
     ( 'x' == ( x ) ) ? 'X' :        \
     ( 'y' == ( x ) ) ? 'Y' :        \
     ( 'z' == ( x ) ) ? 'Z' :  ( x ) \
    )

I really didn’t want to deprive this of you. :D

Pretty cool to write this really terrifying macro instead of:

#define TO_UPPER(c) c^0x20

which is indeed the shortest way ;)

post Avoid making useless new object

June 4th, 2008

Filed under: .NET, C++ — Kai @ 3:16 pm

You often see statements like the one here when programmers want to check if a string has value or not.

if(strName!="")
{ ... }

For C++ programmers (who uses CString for example) this is correct and not really unusual - but please if you’re writing code in C# or another .NET language keep in mind that this causes the allocation of a new String object just for the reason to compare it with an empty string.

Correct implementations would be:

if(strName.Length <= 0)
{ ... }
 
if(strName.Length == 0)
{ ... }

You will not regognize this in a performance test or when using the application but it’s just good form to do it right - also because you know why you should do.

When working with CStrings it’s dispensable faster or slower to compare with an empty string or just to compare the length. If you have a look at the IsEmpty() member function of CString Class you’ll mention that I’m right:

bool IsEmpty() const throw()
{
     return( GetLength() == 0 );
}
ruldrurd
« Previous PageNext Page »
Powered by WordPress, Content and Design by Kai Bellmann
Entries (RSS) and Comments (RSS)