Click Here!
home account info subscribe login search FAQ/help site map contact us


 
Brief Full
 Advanced
      Search
 Search Tips
[an error occurred while processing this directive]
Previous Table of Contents Next


Making Your Structure Work with All Settings

The most common way to make your structure work with all settings is to byte-pad structures to make sure (for the PC architecture) they take up some multiple of 4 bytes. This ensures the alignment will be the same for compilers using any of the three settings for compilation. A more alignment-safe structure would look like this:

struct {
     char MyChar ;
     char[3]/* reserved */ ;
     long int myLongInt ;
} MyStruct ;

Some compilers might insist that you name the second data member, but most don’t.

You should watch for structure alignment issues when working with binary files, binary data transfers, operating system, and even lower level structures. Mismatched byte-alignment settings cause all sorts of bugs (in the form of garbage values) to creep into your programs.

Steps

Probably the easiest way is to use the sizeof() operator to return the size of the objects that are being worked with.

For example, to output the size of a previously declared class MyClass, use

cout << “Size of myclass: ” << sizeof( MyClass) << endl ;

If this seems like too much work, try adding up the data member according to the sizes above.

This will also show possible byte-alignment problems. Anytime your structure or class contains chars, a little flag should go up to ensure the structure is byte-alignment safe. I call this defensive coding, and it can save you a lot of long hours and lost sleep.

12.4 Prevent memory leaks caused by not using delete[] to delete arrays?

Problem

Using the delete operator on an array does not delete all the memory allocated for the array. delete[] must be used instead.

Technique

A memory debugger such as Inprise’s venerable Borland CodeGuard tool can be invaluable as a safety check for your code. Other systems and compilers either come with their own memory-debugging library or have one available for them.

Source code analyzers can often detect these errors, too—tools such as lint can be very useful for finding all sorts of possible problems with code.

Steps

Check your code for any statements that allocate arrays with new, and find the corresponding delete statement.

Whenever an array is allocated with new, the actual operator used is new[]. Unfortunately, most documentation and programmers’ texts do not distinguish between the two for fear of confusing beginning programmers.

Allocating an array like this

char* myArray = new char[45] ;

calls new[], although the brackets appear later on. Free the storage allocated this way:

delete[] myArray ;

The steps for this How-To are relatively simple:

1.  Find all occurrences of new in your code. Utilities such as grep are useful for this.
2.  Check to see if these new operators allocate arrays.
3.  Ensure that the delete[] operator is used to delete the arrays.

How It Works

The delete[] syntax is used to explicitly inform the memory manager that an entire section is to be deleted. Although most memory managers do keep detailed information on the memory allocated, calling plain delete for an array deletes the first location of the array, and nothing else, by definition.

Some memory managers are smarter than this, but at times they will have compatibility problems with some C++ code that exploits this “feature.”

12.5 Override the new or delete operators for my classes?

Problem

There are lots of possible reasons you would want to override the standard new and delete operators for a class or even an entire program.

Here is a short list of things that can be accomplished by overloading the new and delete operators (this is by no means complete):

  Debugging your program’s memory management.
  Taking advantage of operating system–specific routines that might be more efficient than the compiler’s included memory allocation routines.
  Gathering statistics for memory allocation and deallocation in your program for performance or efficiency reasons.

Technique

Overriding the new and delete operators for classes is achieved very much the same way any other operator is overloaded. The only thing that really needs to be known is the number of bytes to be allocated for the new operator:

void* myclass::operator new(size_t bytes_to_allocate)

The function must return a pointer of type void, and takes a size_t argument (usually defined as a 32-bit int in the file stddef.h, which you might have to include) to indicate the size of the object. This is the same number returned by the built-in function sizeof().

The delete operator does not return anything; it takes a void pointer and size_t as arguments.

void myclass::operator delete(void* obj, size_t size)

Again, size_t is defined in stddef.h, and this will likely need to be included in your program.

There is quite a caveat attached to this technique, however. Remember the previous discussion of the operator delete[]? The technique shown here does not overload this operator, nor the new[] version thereof. That means the overloading technique is only really useful for some debugging and statistics work. Granted, everyone uses STL vector classes now, right? (Now there’s a subtle hint...)

Allocating the memory is also possibly tricky—it is easiest to allocate the space using an array of char. However, some platforms, such as Unicode-based systems, do not use 1-byte characters. Production code should determine the size of a char before allocating the memory to ensure that twice the memory needed is not allocated by accident.


Previous Table of Contents Next


Products |  Contact Us |  About Us |  Privacy  |  Ad Info  |  Home

Use of this site is subject to certain Terms & Conditions, Copyright © 1996-1999 EarthWeb Inc.
All rights reserved. Reproduction whole or in part in any form or medium without express written permision of EarthWeb is prohibited.