VC++/MFC

Open Source Project's in VC++ & MFC

Here are some of the opensource projects written in Visual C++. These are very good refrence for all VC++ programmers.

Visual C++ Debugging: How to use 'ASSERT' and deal with assertions failures?

Q: What is an assertion?
A: An assertion statement specifies a condition that you expect to hold true at some particular point in your program. If that condition does not hold true, the assertion fails, execution of your program is interrupted, and the Assertion Failed dialog box appears.

Q: What kind of asserts does Visual C++ support?
A: Visual C++ supports assertion statements based on the following constructs:

  • 'MFC assertions' for MFC program
  • 'ATLASSERT for programs that use ATL
  • 'CRT' assertions for programs that use the C run-time library
  • ANSI 'assert()' function for other C/C++ programs

Q: What good are assertions for?
A: You can use assertions to:

  • Catch logic errors
  • Check results of an operation
  • Test error conditions that should have been handled

Q: What is MFC's ASSERT?
A: A macro definition that allows you to evaluate an expression. If the expression is evaluated to 0, the macro prints a diagnostic message and aborts the program. If the condition is nonzero, it does nothing. The diagnostic message has the form

assertion failed in file _filename_ in line _linenum

where '_filename_' is the name of the source file, and '_linenum_' is the line number of the assertion that failed in the source file. In an MFC ISAPI application, an assertion in debug mode will bring up a modal dialog box; this will interrupt or hang the execution.

: Are there another MFC assertion macros?

A: Yes, you can also use one of these:

  • 'ASSERT_KINDOF(classname, pobject)' -> This macro asserts that the object pointed to is an object of the specified class, or is an object of a class derived from the specified class.
    ASSERT_KINDOF(CMyDocument, pDocument)

    if identical with
    ASSERT(pobject->IsKindOf(RUNTIME_CLASS(classname)));
  • 'ASSERT_VALID(pobject)' -> Used to test an assumptions about the validity of an object's internal state. The parameter must be an object of a class derived from 'CObject' that has an overriding version of the 'AssertValid()' member function. 'ASSERT_VALID' validates the pointer, checks against 'NULL', and calls the object's own 'AssertValid()' member functions.

Q: What about 'ATLASSERT'?
A: The 'ATLASSERT' macro performs the same functionality as the '_ASSERTE' macro found in the C run-time library.

Q: What are the CRT assertion macros?
A: The 'CRTDBG.H' header file defines the '_ASSERT' and '_ASSERTE' macros for assertion checking. The result of these macros are:

  • '_ASSERT: If the specified expression evaluates to FALSE, the file name and line number of the _ASSERT
  • '_ASSERTE': Same as _ASSERT, plus a string representation of the expression that was asserted

Q: How do I chose between '_ASSERT' and '_ASSERTE'?
A: '_ASSERTE' is more powerful because it reports the asserted expression that turned out to be 'FALSE'. This may be enough to identify the problem without referring to the source code. However, the Debug version of your application will contain a string constant for each expression asserted using '_ASSERTE'. If you use many '_ASSERTE' macros, these string expressions take up a significant amount of memory. If that proves to be a problem, use '_ASSERT' to save memory.

Q: And about the ANSI assertion funtion?

A: 'assert()' evaluates an expression and, when the result is 'false', prints a diagnostic message and aborts the program.

The ANSI 'assert' macro is typically used to identify logic errors during program development by implementing the expression argument to evaluate to 'false' only when the program is operating incorrectly. After debugging is complete, assertion checking can be turned off without modifying the source file by defining the identifier 'NDEBUG'. 'NDEBUG' can be defined with a '/D' command-line option or with a '#define' directive. If 'NDEBUG' is defined with '#define', the directive must appear before 'Assert.h' is included.

'assert' prints a diagnostic message when expression evaluates to 'false' (0) and calls abort to terminate program execution. No action is taken if expression is 'true' (nonzero). The diagnostic message includes the failed expression and the name of the source file and line number where the assertion failed.

Q: Can I see an example of 'assert()'?
A: Here is a simple example and the output. Consider the file is called 'test.cpp':

#include <assert.h>
int main()
{
int* array = NULL;
assert(array != NULL); // this should fail
return 0;
}

output is:

Assertion failed: array != NULL, file test.cpp, line 7
abnormal program termination

 

Q: Do asserts work in release version also?
A: No, only in debug version. In the release version of MFC, 'ASSERT' does not evaluate the expression and thus will not interrupt the program. If the expression must be evaluated regardless of environment, use the 'VERIFY' macro in place of 'ASSERT'. Because of this, never use a method that changes the state of the program as the expression or part of the expression of 'ASSERT'. In a release build, 'ASSERT' is not included in the code.

Q: What should I do when I get a "Debug Assertion Failed!" message?
A: Run your application in debugger and when you get the message press 'Retry' to debug the application. Look in the 'call stack' window (Alt+7) and go to the first (from top down) function written by you in the stack and identify the line that triggers the assertion failure.

Q: What are common causes for assertion failures?
A: Most often it is the usage of an invalid pointer or an attempt to index an array beyond its boundaries.

Q: How can 'ASSERT' help me with writing better code?
A: You build your application first as a debug version and only when it is finished you build the release version. 'ASSERT' help you identify the errors in the execution flow. You should always test pointers for validity:

void Draw(int index)
{
CFigure* pFigure
= GetFigure(index); // should return a figure from a list
// if GetFigure returns NULL the next line of code is faulty
pFigure->Draw ();
}

The correct way is:

void Draw (int index)
{
CFigure* pFigure
= GetFigure(index);
ASSERT(pFigure != NULL); // if pFigure == NULL you get an error message
if(pFigure == NULL) // this avoids the usage of a NULL pointer
return;
pFigure->Draw ();
}

In this example, I consider 'GetFigure()' a function that should always return a valid figure. The role of 'ASSERT' is to ensure that 'GetFigure()' actually does what it supposed to do and always return a valid pointer. Now if you wander what is the role of

if(pFigure == NULL) return;

the answer is to make sure that if the debug build wasn't tested enough and an error could occur in the release, the program wouldn't crash because of the use of a 'NULL' pointer.

However, if 'GetFigure()' can return a 'NULL' pointer, that pointer should not be asserted against 'NULL'.

You should also test the index used for accessing elements of arrays:

// this is a dummy example
class foo
{
int elements[10];
public
:
foo() {
/* do some initialization */ };
int
getAt(int index) const
{
ASSERT(index>
=0 && index<10);
if
(index>=0 && index<10)
return elements[index];
return
-1; // return a default value
}
}
;

 

Note: Most of the material in this article is taken from codeguru.com


Recommended Reading :

Visual C++ DLL: How to build a resource-only DLL?

Q: How to build a resource-only DLL?
A: On the 'Project Menu', select 'Settings'. Select the 'Link' tab of the 'Project Settings' dialog, then in the 'Project Options' box, add the '/NOENTRY' option. '/NOENTRY' prevents the linker from linking a reference to '_main' into the DLL; this option is required to create a resource-only DLL.

  1. Add the .RC file to an empty DLL project.
  2. Build the DLL.

No MFC is involved in this process. If your application needs to access the resources from the DLL, it is easier to use the Win API functions to access these resources than MFC. You need to call 'LoadLibrary()' with the name of resource DLL, and then the Windows API 'FindResource()'/'LoadResource()'/'LoadBitmap()' etc. functions to find and load the resource.

The reason why the API functions are easier to manage than MFC is that the API functions require that you give it the handle to the loaded DLL (the return value when you called 'LoadLibrary()'), while the MFC functions do not have this parameter. Requiring the DLL handle allows much more flexibility, since you can have multiple resource DLL's loaded, and you don't have to fool around with the 'AfxSetResourceHandle()' function (for example, compare the MFC 'LoadBitmap()' with the Windows API 'LoadBitmap()'). When you call 'AfxSetResourceHandle()', you are globally making a change to which resources your application is going to reference, which I do not like, so I don't ever use that function.

If you want to use the MFC functions after using the API function to load your bitmap, just call the 'Attach()' method, and then the 'Detach()' method.

Note: Most of the material in this article is taken from codeguru.com


Recommended Reading :

Visual C++ Debugging: How do I evaluate the time difference between two events?

Q: How do I evaluate the time difference between two events?
A: Accurate time difference between events cannot be evaluated by clocking the time using 'CTime::GetCurrentTime()' or by using a timer. First method is limited in its accuracy to around a second and second method has limitations of lower priority.

Here I present a function which returns the time elapsed from the last call. First call will always return a zero value. This uses the high-resolution performance counter. If it does not exist, each call will return zero.

float TimeDiff()
{
// Last counter reading
static LARGE_INTEGER OldCounter = {0, 0};
LARGE_INTEGER Counter, Frequency;
if
(QueryPerformanceFrequency(&Frequency))
{
// Gets current counter reading
QueryPerformanceCounter(&Counter);
// Calculates time difference (zero if called first time)
float TimeDiff = OldCounter.LowPart ? (float) (Counter.LowPart - OldCounterLowPart) / Frequency.LowPart : 0;
// Resets last counter reading
OldCounter = Counter;
// Returns time difference
return TimeDiff;
}
else
{
// No high resolution performance counter; returns zero
return 0;
}
}

Time difference is returned in seconds and the accuracy is determined by the high-resolution performance counter frequency.
Note: Most of the material in this article is taken from codeguru.com


Recommended Reading :

Visual C++ Network: How to get the local IP address(es)?

Q: How to get the local IP address(es)?
A: The following example will get up to ten assigned IP addresses...

#include <winsock2.h>
// Add 'ws2_32.lib' to your linker options
WSADATA WSAData;
// Initialize winsock dll
if(::WSAStartup(MAKEWORD(1, 0), &WSAData))
// Error handling
// Get local host name
char szHostName[128] = "";
if
(::gethostname(szHostName, sizeof(szHostName)))
// Error handling -> call 'WSAGetLastError()'
// Get local IP addresses
struct sockaddr_in SocketAddress;
struct
hostent *pHost = 0;
pHost = ::gethostbyname(szHostName);
if
(!pHost)
// Error handling -> call 'WSAGetLastError()'
char aszIPAddresses[10][16]; // maximum of ten IP addresses
for(int iCnt = 0; ((pHost->h_addr_list[iCnt]) && (iCnt < 10)); ++iCnt)
{
memcpy(&SocketAddress.sin_addr, pHost->h_addr_list[iCnt], pHost->h_length)
;
strcpy(aszIPAddresses[iCnt], inet_ntoa(SocketAddress.sin_addr));
}
// Cleanup
WSACleanup();

As with everything, there exists of course other ways and other information which can be retrieved...some examples can be found in the following knowledge base article.

Note: Most of the material in this article is taken from codeguru.com


Recommended Reading :

Visual C++ Network: How to get the local hostname?

Q: How to get the local hostname?

A:

#include <winsock2.h>

// Add ws2_32.lib to your linker options

WSADATA WSAData;

// Initialize winsock dll
if(::WSAStartup(MAKEWORD(1, 0), &WSAData) == FALSE)
// Error handling

// Get local host name
char szHostName[128] = "";

if
(::gethostname(szHostName, sizeof(szHostName) - 1))
// Error -> call 'WSAGetLastError()'

// Cleanup
WSACleanup();
Note: Most of the material in this article is taken from codeguru.com
Recommended Reading :

Visual C++ DLL: How to build a DLL to be used from another programming language?

Q: How to build a DLL to be used from another programming language?

A: When you create a DLL with Visual C++, and you want to use the DLL with other languages, there are a few things that you should do (creating a DLL isn't just compiling code).

  1. Make sure your exported functions are declared as extern "C". The reason for this is so that the C++ name mangling is not used on the exported function names.
  2. Make sure your exported functions use '__stdcall' calling convention. The reason for this is that most other Window's languages assume the exported functions retrieve parameters starting from the rightmost parameter, and that the function called is responsible for stack cleanup on return. By default C and C++ functions assume '__cdecl' calling convention.
    You won't know when this problem exists until you call the exported function in your Delphi program. You did not declare
    your function as '__stdcall', so your [insert porgramming language, other than C/C++, here] program would have crashed as soon as you called the function.
  3. Use '__declspec(dllexport)'. This is so that the function can be exported (of course).
  4. Use a module definition file (.def-file). This removes the "@x" decoration that appears at the end of VC++ exported function names, where "x" is the total number of bytes in the arguments passed to the function. When the user of the DLL is using another language, the programmer would rather call "tempest", not "tempest@4". Yes, many of these other languages have an "aliasing" features so that you can access the function by a different name, but it is a pain in the neck. Just use a .def-file to remove the additional decoration and you won't have to do anything else.

Note: Just exporting the name does *not* remove all the decoration - you must follow steps a) *and* d). A lot think that you only need to do a) and b) and c). This is if you plan on using the DLL in only Visual C++. If you leave the module definition file out of these steps, you will get what you're seeing now -- an exported name that is not what you expect.

If you do a search on CodeGuru, your question has been asked many times in various ways, and the reason for the problem is almost always that step d) was left out.
Here is a sample of a module-definition fie (DEF file).
LIBRARY YOURDLL
DESCRIPTION 'This is my DLL
EXPORTS
Whatever1 @2
Whatever2 @3

The LIBRARY command must match the name of your DLL. So if your DLL is named YOURDLL.DLL, the LIBRARY command is followed by YOURDLL.

The DESCRIPTION is any description you feel is appropriate for your DLL. The actual description is preceeded by a single quote (').

The EXPORTS lists the functions that you exported, along with an ordinal number. It doesn't matter what ordinal numbers you use, so long as you maintain different numbers for each function, and you shouldn't change the ordinal numbers when you create an upgraded version of your DLL -- persons preferring to use ordinal numbers to call your functions will get angry.
Note: Most of the material in this article is taken from codeguru.com

 


Recommended Reading :

Visual C++ General: How to use different character sets?

Q: I have this simple function call:

MessageBox(NULL, "Test message", "Title", MB_OK);


The compiler raises the following error and I don't understand why.

error C2664: 'MessageBoxW' : cannot convert parameter 2 from 'const char [13]' to 'LPCWSTR'
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

A: Simply answered, that happens because the project is built for UNICODE.

Microsoft run-time library provides Microsoft-specific generic-text mappings for many data types, routines and other objects, mappings that are defined in TCHAR.h. There are three supported character sets:[/list][*]ASCII (single-byte character set

Syndicate content



Loans - Phoenix Pools - Car Insurance - Credit Card Consolidation