How to fix IntelliSense errors in Visual Studio

New Visual Studio C/C++ users sometimes get tripped up by IntelliSense errors, so today I’ve decided to share the secret, undocumented solution: just turn them off!

IntelliSense is a nice user interface feature when it works, but it has nothing whatever to do with building and running your C/C++ code. IntelliSense errors do not equal compiler errors, and trying to “fix” them is fruitless.

Simply right-click anywhere on the Visual Studio error list (the click must be inside the list, not outside), then uncheck “Show IntelliSense Errors”. Problem solved!

The 'Show IntelliSense Errors" toggle.

There is one small irritating issue with this solution: your setting is not persisted in the registry, so the errors have to be turned off every time you start Visual Studio.

Writing a Custom Debugger on Windows

Recently I had to debug an intermittent access violation exception in one of my AutoCAD plug-ins. I needed to get the exception while the debugger was attached so I could break the process and analyze the state of memory before AutoCAD’s global exception handler got control. Unfortunately, sometimes it took several hundred runs before the exception occurred.

To make matters worse, AutoCAD was throwing exceptions on shutdown that had nothing to do with my code. If I started AutoCAD manually under the Visual Studio debugger, I had to dismiss those shutdown exceptions manually every time. I needed a way to script the task of starting AutoCAD under the debugger hundreds of times in a row until the exception finally occurred.

After some futile attempts to script the Visual Studio debugger, I decided to just write my own custom debugger. With my own custom debugger, I could easily write code to decide at runtime which exceptions to ignore and which were of interest. The exception I was interested in always occurred while accessing a memory location that ended in 0x30, so my custom debugger ignores access violations that don’t fit the pattern.

I had also planned to see if I could suspend the main thread, detach my custom debugger, and manually attach the Visual Studio debugger when my target exception was triggered so that I could utilize the more advanced VS debugger UI. In the end I never got around to trying the debugger switch because I discovered the problem by simply displaying some relevant details in a simple message box when the target exception occurred.

As you can see, I hardcoded the application path and command line, which includes a script file that simply quit AutoCAD after it started. I then used a batch file to run the custom debugger in a loop, thereby starting and quitting AutoCAD each time through the loop. I made this debugger a console app, but it could just as well be a window app.

I don’t claim to know anything about writing debuggers; this is just something I cobbled together after doing a bit of searching on the web. I decided to share the code in case someone else runs into a similar debugging scenario.

int _tmain(int argc, _TCHAR* argv[])
{
STARTUPINFO si;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
PROCESS_INFORMATION pi;
ZeroMemory( &pi, sizeof(pi) );
static TCHAR szCmdLine[] = _T(" /nologo /b C:\Test\quit.scr");
CreateProcess ( _T("C:\Program Files\Autodesk\AutoCAD 2014\acad.exe"), szCmdLine, NULL, NULL, FALSE, DEBUG_ONLY_THIS_PROCESS, NULL,NULL, &si, &pi );

DWORD dwContinueStatus = DBG_CONTINUE;
DEBUG_EVENT debug_event = {0};
bool bFirstBreakpoint = false;
bool bContinueDebugging = true;
while( bContinueDebugging )
{
if( !WaitForDebugEvent( &debug_event, INFINITE ) )
return 0;
//process event
switch( debug_event.dwDebugEventCode )
{
case EXIT_PROCESS_DEBUG_EVENT :
{
bContinueDebugging = false;
}
break;

case EXCEPTION_DEBUG_EVENT:
{
dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
EXCEPTION_DEBUG_INFO& exception = debug_event.u.Exception;
switch( exception.ExceptionRecord.ExceptionCode )
{
case STATUS_BREAKPOINT:
{
if( !bFirstBreakpoint )
{
bFirstBreakpoint = true;
break;
}
dwContinueStatus = DBG_EXCEPTION_HANDLED;
DebugActiveProcessStop(pi.dwProcessId);
bContinueDebugging = false;
MessageBox(NULL,_T("Debug break!"), _T("Breakpoint"), MB_OK);
}
break;

case STATUS_ACCESS_VIOLATION:
if( exception.dwFirstChance == 1 )
{
if( ((DWORD_PTR)exception.ExceptionRecord.ExceptionAddress & 0xFF) == 0x30 )
{
DebugActiveProcessStop(pi.dwProcessId);
DWORD64 Rip = (DWORD64)-1;
HANDLE hThread = OpenThread( THREAD_ALL_ACCESS, FALSE, debug_event.dwThreadId );
CONTEXT Context;
Context.ContextFlags = CONTEXT_ALL;
if( GetThreadContext(hThread, &Context) )
Rip = Context.Rip;
MEMORY_BASIC_INFORMATION mbi = { 0 };
VirtualQueryEx( pi.hProcess, exception.ExceptionRecord.ExceptionAddress, &mbi, 0x36 );
TCHAR szMsg[4096];
_stprintf_s( szMsg, _T("Access violation (%016p) at address %016prnMem State:rnBaseAddress=%016prnAllocationBase=%016prnAllocationProtect=%08xrnRegionSize=%08xrnState=%08xrnProtect=%08xrnType=%08x"), exception.ExceptionRecord.ExceptionCode, exception.ExceptionRecord.ExceptionAddress, mbi.BaseAddress, mbi.AllocationBase, mbi.AllocationProtect, mbi.RegionSize, mbi.State, mbi.Protect, mbi.Type );
MessageBox( NULL, szMsg, _T("Exception"), MB_OK );

}
bContinueDebugging = false;
}
break;

default:
break;
}
}
break;
}
ContinueDebugEvent( debug_event.dwProcessId, debug_event.dwThreadId, dwContinueStatus );
}

return 0;
}

C++ function declaration tips

Creating and calling functions is one of the most fundamental tasks in C++ programming. The function declaration serves as the primary description of a function’s interface – or contract – with callers, thereby making it the most important piece of code documentation. A good function declaration should convey as much information as possible. I’m sure an entire book could be written on the topic of function interface design, but I’ll just touch briefly on a few factors to consider when designing a function’s interface.

Error handling

Simple one-purpose functions should leave all or most error handling to the caller. This is more efficient because it eliminates error checking overhead on “known good” input values. A common pattern is a low level function that performs no input validation along with a high level function that does (and then calls the low level function to do the work). Such a design pattern gives the caller maximum flexibility.

If the function must return error (or other status) values, it should do so via the return value whenever possible, and it should define an enum or type alias (typedef) so that the return value type name makes it clear that the value is a status. Note that using the return value as a status may necessitate extra arguments passed by reference so the function has a way to return a result to the caller without using the return value.

Signed vs. unsigned

Consider this function:
int CountWords(char* pszInputString);

The int type is a signed value, but a count is always zero or greater. The return value should at least be unsigned int, or better yet size_t:
size_t CountWords(char* pszInputString);

Likewise, arguments that must never be negative should always be declared as an unsigned type.

By value or by reference

If the caller needs to pass arguments that the function will modify, they must be passed by reference. If the argument will not be modified, then it should be passed by value if it is a trivial type, else by const reference (except in unusual cases). For example:
bool CountWords(const CountOptions& options, char* pszInputString, size_t& ctWords);

Const or not

Incoming arguments that will not be modified should be declared const. This conveys a clear guarantee that the function will not try to modify the incoming value. Proper const delarations also give the optimizing compiler more ways to optimize the code.

Since counting words does not require the input string to be modifed, the CountWords() function’s string argument should really be const char* const (constant pointer to constant char) instead of char*:
size_t CountWords(const char* const pszInputString);

Now the caller can pass a string literal or any other string (even an MFC CString), and be assured that the CountWords function won’t change it.

Source code annotation language

Source code annotation language (SAL) is a fairly recent Microsoft specific development. It consists of predefined macros that help more fully express the constraints and purposes of function arguments without changing the compiled output. SAL helps convey additional information about the function’s contract with the caller, and it also helps the compiler detect potential problems at compile time by performing additional static code analysis.

As you can see below, source code annotation can get a bit messy. I rarely use source code annotation in my own code for this reason and also because it’s not portable to older versions of Visual Studio without extra work. Source code annotation is most appropriate in an API that will be consumed by others, and even then it should be considered carefully in light of its readability and portability trade-offs.

Exception specification

In C++, the exception specification conveys information about what kinds of exceptions a function may throw, either directly or indirectly via functions it calls. If a function cannot throw an exception, you should include the empty throw() suffix on the function declaration.

Putting it all together

Suppose we create a higher level function that validates the input, then calls a lower level function to count words. We might end up with something like this:

size_t CountWords(_In_z_ const char* const pszInputString) throw();

enum Status { eOK, eNull, eError, };

_Check_return_ Status ValidateAndCountWords(_In_z_ const char* const pszInputString, _Out_ size_t& ctWords) throw();

Using /delayload to specify dependent DLL path

Let’s say you have an ObjectARX module with an implicit dependency on another DLL. Your installer puts both your ARX module and the dependent DLL into a private application folder. Windows must be able to resolve the implicit DLL dependency at load time, otherwise it will fail to load your ARX module. Alas, Windows will not automatically search for the dependent DLL in your application folder, even though your ARX module is located there. Therefore your ARX module won’t load because the dependent DLL cannot be resolved.

To address this problem, you may be tempted to add your application folder to the AutoCAD support path so that Windows can find your dependent DLL. This is a Very Bad Idea – please don’t ever do it! It imposes a completely unnecessary burden on end users, and it’s not scaleable because it could cause the maximum support path length to be exceeded. A better solution is to change the implicit dependency into an explicit dependency by using the linker’s delayload feature.

Making the change is easy. First, change your ARX project’s linker settings to delayload the dependent DLL:

delayload

Next, implement a delayload hook in one of your source files to explicitly load the dependent DLL from the same folder as your ARX module:

#include <delayimp.h>

#pragma comment(lib, "delayimp")

HMODULE MyExplicitLoadLibrary( LPCSTR pszModuleName )
{
  if( lstrcmpiA( pszModuleName, "MyDependent.dll" ) == 0 )
  {
    CHAR szPath[MAX_PATH] = "";
    //_hdllInstance is the HMODULE of *this* module
    DWORD cchPath = GetModuleFileNameA( _hdllInstance, szPath, MAX_PATH );
    while( cchPath > 0 )
    {
      switch( szPath[cchPath - 1] )
      {
        case '\':
        case '/':
        case ':':
          break;
        default:
          --cchPath;
          continue;
      }
      break; //stop searching; found path separator
    }
    lstrcpynA( szPath + cchPath, pszModuleName, MAX_PATH - cchPath );
    return LoadLibraryA( szPath ); //call with full path to dependent DLL
  }
  return NULL;
}

FARPROC WINAPI MyDliNotifyHook( unsigned dliNotify, PDelayLoadInfo pdli )
{
  if( dliNotify == dliNotePreLoadLibrary )
    return (FARPROC)MyExplicitLoadLibrary( pdli->szDll );
  return NULL;
}
extern "C" PfnDliHook __pfnDliNotifyHook2 = MyDliNotifyHook;

When you use this technique, you do have to ensure that the delayload hook is added before any function in the dependent DLL is called. This is not a problem in most cases, but it could be a consideration if your ARX module initializes global objects whose constructors must call functions in the dependent DLL. This is just one more reason why you should avoid global variables.

Polymorphic bit flags in C++

I often encounter cases in ObjectARX programming where numerous boolean flags need to be persisted as part of an AutoCAD database object. For filing and for passing around to other functions, it’s most efficient to package those bit flags into a single unsigned integer. Below is an example that demonstrates how to use a union inside a containing class that can be simultaneously used as either a single unsigned integer or as individual booleans.


// first declare a compact bitflag structure as bool values
struct FlagsAsBools
{
bool flag1 : 1;
bool flag2 : 1;
bool flag3 : 1;
bool flag4 : 1;
bool flag5 : 1;
bool flag6 : 1;
bool flag7 : 1;
bool flag8 : 1;
bool flag9 : 1;
bool flag10 : 1;
bool flag11 : 1;
bool flag12 : 1;
};

// now the containing class with useful constructors and operators
class Flags
{
protected:
// and the hidden union that actually contains the flags
union _Flags
{
FlagsAsBools asBools;
Adesk::UInt32 asUInt; //space for up to 32 flags
} mFlags;
public:
Flags()
{
mFlags.asUInt = 0;
}
Flags(Adesk::UInt32 flags)
{
mFlags.asUInt = flags;
}
Flags(const FlagsAsBools& flags)
{
mFlags.asBools = flags;
}
operator Adesk::UInt32 () const { return mFlags.asUInt; }
const FlagsAsBools& asBools() const { return mFlags.asBools; }
FlagsAsBools& asBools() { return mFlags.asBools; }
};

// now a class that contains the flags
class Settings
{
AcString msSomeStringSetting;
bool mbSomeBoolSetting;
Flags mFlags;
public:
Settings () : mbSomeBoolSetting(false) {}

LPCTSTR someStringSetting() const { return msSomeStringSetting; }
void setSomeStringSetting(LPCTSTR someStringSetting) { msSomeStringSetting = someStringSetting; }
bool someBoolSetting() const { return mbSomeBoolSetting; }
void setSomeBoolSetting(bool someBoolSetting) { mbSomeBoolSetting = someBoolSetting; }
Flags flags() const { return mFlags; }
void setFlags(Flags flags) { mFlags = flags; }
};

// now use the flags as an argument to a function in different forms
void DoStuffBasedOnFlags( Adesk::UInt32 flags )
{
if( Flags(flags).asBools().flag7 )
{// do something when flag7 is set
}
}

void DoOtherStuffBasedOnFlags( const Flags& flags )
{
if( flags.asBools().flag1 )
{// do something when flag1 is set
}
}

void TestIt()
{
Settings& MySettings = GetSettings();
Flags flags = MySettings.flags();
if( flags.asBools().flag4 )
{// do something when flag4 is set
}
DoStuffBasedOnFlags( flags );
DoOtherStuffBasedOnFlags( flags );
flags.asBools().flag2 = true;
MySettings.setFlags( flags ); //save the new settings
}