Test Dynamic Memory

I

Immortal Nephi

I notice that some codes do not have to test dynamic memory to
determine if dynamic memory is available or not. It is said in Deitel
How to Program C++ book.

Is it necessary to test dynamic memory if memory is very small like
less than 256 bytes? The test should fail and prevent you from doing
class constructor.

array class is already constructed before dynamic memory is tested.
If it fails, error message is displayed before exit() function
terminates the program. If I decide to allow the program running
after dynamic memory reported out of memory, then array class should
use destructor to clean up all data members and release array class
from the memory.

For example:

class array
{
public:

array( int size )
{
m_pArray = new int[ size ];
m_size = size;

if( m_pArray == 0 )
{
// Display Error Message -- out of memory
// Close other application and try again or
// use exit() function

// if( yes )
// exit();
// else ( no and continue )
m_bOutofMemory = true;
return;
}
}

~array()
{
if( m_pArray != 0 )
{
delete [] m_pArray;
m_pArray = 0;
}
}

bool TestMemory()
{
return m_bOutofMemory;
}

private:
int m_size;
int *m_pArray;
bool m_bOutofMemory;
};

int main()
{
array *a = new array( 5 );
if( a->TestMemory() == true )
delete a;

// Continue the program after
// exit() function is not invoked.

system( "pause");
return 0;
}
 
J

joseph cook

I notice that some codes do not have to test dynamic memory to
determine if dynamic memory is available or not.  It is said in Deitel
How to Program C++ book.

Is it necessary to test dynamic memory if memory is very small like
less than 256 bytes?  The test should fail and prevent you from doing
class constructor.

Amusingly enough, in C++, the regular new operator can never return 0,
so any test is useless. (A failed allocation will instead throw an
exception).

Of course, if you are working on some embedded systems that may have
disabled exceptions, check your documentation.
Joe Cook
 
P

peter koch

I notice that some codes do not have to test dynamic memory to
determine if dynamic memory is available or not.  It is said in Deitel
How to Program C++ book.

If it says so, it is a bad book.
Is it necessary to test dynamic memory if memory is very small like
less than 256 bytes?  The test should fail and prevent you from doing
class constructor.

If new fails, standard behaviour is to throw std::bad_alloc. Some very
old compilers got that wrong, noticeably VC6.0. If you use that
compiler and can't change, you can change a setting to make it
standards-compliant in that respect.
array class is already constructed before dynamic memory is tested.
If it fails, error message is displayed before exit() function
terminates the program.  If I decide to allow the program running
after dynamic memory reported out of memory, then array class should
use destructor to clean up all data members and release array class
from the memory.

You do realize, that you are just creating a dumped-down version of
std::vector? So your class is useless if not as an exercise. Also, you
are missing a lot of stuff - an assignment operator and a copy
constructor needs to be written.
For example:

class array
{
public:

        array( int size )
        {
                m_pArray = new int[ size ];
                m_size = size;

                if( m_pArray == 0 )
                {
                        // Display Error Message -- out of memory
                        // Close other application and try again or
                        // use exit() function

This behaviour is better delegated into the new_handler function.
                        // if( yes )
                        // exit();
                        // else ( no and continue )
                        m_bOutofMemory = true;
                        return;
                }
        }

Prefer initialization rather than assignment. Your constructor should
be
array( int size ): m_size(size),m_pArray(new int[ size ]) {}

Also notice that m_bOutofMemory only gets initialised in case there is
a memory leak, so you are likely to run into undefined behaviour in
TestMemory.
        ~array()
        {
                if( m_pArray != 0 )

There is no need for this check.
                {
                        delete [] m_pArray;
                        m_pArray = 0;

And no need for this assignment.
                }
        }

        bool TestMemory()
        {
                return m_bOutofMemory;
        }

private:
        int m_size;
        int *m_pArray;
        bool m_bOutofMemory;

That hungarian notation really creeps me out.
};

int main()
{
        array *a = new array( 5 );

Why do you want to allocate a dynamically? This is just silly. Use
array a(5);
        if( a->TestMemory() == true )

Why do you compare to true - this is just obfuscation. Prefer:
if( a->TestMemory() )
                delete a;

        // Continue the program after
        // exit() function is not invoked.

        system( "pause");
        return 0;

Here you have a memory leak - because of the dynamic allocation of a.
 
I

Immortal Nephi

If it says so, it is a bad book.




If new fails, standard behaviour is to throw std::bad_alloc. Some very
old compilers got that wrong, noticeably VC6.0. If you use that
compiler and can't change, you can change a setting to make it
standards-compliant in that respect.




You do realize, that you are just creating a dumped-down version of
std::vector? So your class is useless if not as an exercise. Also, you
are missing a lot of stuff - an assignment operator and a copy
constructor needs to be written.

I build my own class. I don't need to use vector because I don't need
all the features such as search or insert element / remove element. I
suppose to put an assignment operator and a copy constructor to
private if I don't need to use them.
For example:
class array
{
public:
        array( int size )
        {
                m_pArray = new int[ size ];
                m_size = size;
                if( m_pArray == 0 )
                {
                        // Display Error Message -- out of memory
                        // Close other application and try again or
                        // use exit() function

This behaviour is better delegated into the new_handler function.

Are you saying? I create some classes to build different objects and
put them into memory. For example, 5 different classes are
constructed successfully and are stored in memory. They will be
destructed after the program exits successfully. If one class
attempts to allocate more memory, then bad allocation must be returned
before new_handler exception is thrown. Correct?

I do not need to test to find out if new keyword returns a pointer
with bad allocation.
For example:

int *a = new int [1000];

if( a == )
exit();

I should use new_handler instead, but I have to use test condition to
find out if a is already allocated.

For example:

int *a = new int [1000];

// Do something

// Are ready to terminate your program. I have to clean up to
deallocate memory.
if( a != )
delete [] a;
                        // if( yes )
                        // exit();
                        // else ( no and continue )
                        m_bOutofMemory = true;
                        return;
                }
        }

Prefer initialization rather than assignment. Your constructor should
be
        array( int size ): m_size(size),m_pArray(new int[ size ]) {}

Also notice that m_bOutofMemory only gets initialised in case there is
a memory leak, so you are likely to run into undefined behaviour in
TestMemory.


        ~array()
        {
                if( m_pArray != 0 )

There is no need for this check.
                {
                        delete [] m_pArray;
                        m_pArray = 0;

And no need for this assignment.
                }
        }
        bool TestMemory()
        {
                return m_bOutofMemory;
        }
private:
        int m_size;
        int *m_pArray;
        bool m_bOutofMemory;

That hungarian notation really creeps me out.
Please explain why you dislike hungarian notation. It provides you
more information when you need to know because there may be hundreds
or thosuands of variables. Anyway...
Why do you want to allocate a dynamically? This is just silly. Use
        array a(5);


Why do you compare to true - this is just obfuscation. Prefer:
        if( a->TestMemory() )




Here you have a memory leak - because of the dynamic allocation of a.

Here is another good example.

#include <iostream>
using std::cerr;
using std::cout;
using std::endl;

#include <new>
using std::set_new_handler;

#include <cstdlib>
using std::abort;
using std::exit;

class array
{
public:
array( int size ) : m_size( size ), m_pLargeArray( new long long
[ size ] )
{
cout << "array::constructor -- count: " << ++s_ObjectCount << endl;
}

~array()
{
cout << "array::destructor -- count: " << s_ObjectCount-- << endl;
delete [] m_pLargeArray;
}

private:
long long *m_pLargeArray;
int m_size;
static int s_ObjectCount;
};

int array::s_ObjectCount = 0;

void customNewHandler()
{
cerr << "customNewHandler was called.\n";
cerr << "Display Error: Not enough Memory.\n\n";
cerr << "Your C++ project must be terminated." << endl;

// abort();
exit( EXIT_SUCCESS );
}

int main()
{
set_new_handler( customNewHandler );

array a1( 50000000 ); // Success
array a2( 50000000 ); // Success
array a3( 50000000 ); // Success
array a4( 50000000 ); // Success
array a5( 50000000 ); // Failed -- bad memory allocation.

cout << "C++ project runs successful." << endl;

return 0;
}

If bad memory allocation is detected, then will exit() function does
its own responsibility to deallocate a1, a2, a3, and a4 from the
memory before program is terminated?

Do you suggest me to put new_handler exception in main.cpp only? All
other headers and source codes are included in main.cpp. new_handler
exception takes care to clean up the rest.
 
I

Ian Collins

Immortal said:
I build my own class. I don't need to use vector because I don't need
all the features such as search or insert element / remove element. I
suppose to put an assignment operator and a copy constructor to
private if I don't need to use them.

There's no cost in not using what you don't need, there is cost in
reinventing wheels, so just use std::vector.
For example:
class array
{
public:
array( int size )
{
m_pArray = new int[ size ];
m_size = size;
if( m_pArray == 0 )
{
// Display Error Message -- out of memory
// Close other application and try again or
// use exit() function
This behaviour is better delegated into the new_handler function.

Are you saying? I create some classes to build different objects and
put them into memory. For example, 5 different classes are
constructed successfully and are stored in memory. They will be
destructed after the program exits successfully. If one class
attempts to allocate more memory, then bad allocation must be returned
before new_handler exception is thrown. Correct?

If new fails, std::bad_alloc will be thrown. If you provide a
new_handler function, it will be called.

On a hosted environment, any allocated memory will be freed when the
process terminates.
I do not need to test to find out if new keyword returns a pointer
with bad allocation.
Correct.
Please explain why you dislike hungarian notation. It provides you
more information when you need to know because there may be hundreds
or thosuands of variables. Anyway...

It creeps out a lot of people. No sane class or function has hundreds
of variables.
Here is another good example.
If bad memory allocation is detected, then will exit() function does
its own responsibility to deallocate a1, a2, a3, and a4 from the
memory before program is terminated?

See above.
Do you suggest me to put new_handler exception in main.cpp only? All
other headers and source codes are included in main.cpp. new_handler
exception takes care to clean up the rest.

You only have to call set_new_handler once.
 
I

Immortal Nephi

There's no cost in not using what you don't need, there is cost in
reinventing wheels, so just use std::vector.

Ok. Do you think that I should use std::vector if list of Multi-
Dimension array contain bitmap images such as font image or picture
image? Perhaps, search feature is needed because some strings have
individual characters and each character in the string is searched
(scanned) before 2-D array with font image is selected to be displayed
to the screen. Also, 2-D array with font image will be copied into
Pixel Buffer before Pixel Buffer is used with DirectX or other graphic
engines.
 
A

aku ankka

Ok.  Do you think that I should use std::vector if list of Multi-
Dimension array contain bitmap images such as font image or picture
image?  Perhaps, search feature is needed because some strings have
individual characters and each character in the string is searched
(scanned) before 2-D array with font image is selected to be displayed
to the screen.  Also, 2-D array with font image will be copied into
Pixel Buffer before Pixel Buffer is used with DirectX or other graphic
engines.

I think, that you need image/surface class where you store information
about the surfaces: width, height, stride, format at least. And the
image data; whether it is std::vector or char* doesn't make much
difference.

OK; so the std::vector will have methods that you are not going to
use, big deal, so what. I wouldn't write my own array class to replace
the vector, though. I'd just use char*. Oh, right - that's what I do!

If I were to use std::vector, it would be std::vector<char> or
std::vector<uint8>, where uint8 is obviously octet, *piip* the
platforms where char ISN'T octet! <- if this isn't mentioned, shit
storm will result in this NG, no offence to anyone. >B)
 
I

Immortal Nephi

I think, that you need image/surface class where you store information
about the surfaces: width, height, stride, format at least. And the
image data; whether it is std::vector or char* doesn't make much
difference.

OK; so the std::vector will have methods that you are not going to
use, big deal, so what. I wouldn't write my own array class to replace
the vector, though. I'd just use char*. Oh, right - that's what I do!

If I were to use std::vector, it would be std::vector<char> or
std::vector<uint8>, where uint8 is obviously octet, *piip* the
platforms where char ISN'T octet! <- if this isn't mentioned, shit
storm will result in this NG, no offence to anyone. >B)

I hate signed integer on all sizes. I zlways use unsigned integer.
Often, strings use signed char or signed wchar_t. Combining unsigned
integer and signed integer are problemtic. I always declare unsigned
char to string because sometimes, I want to use between 128-256 range
ASCII or unicode.

I agree with you. You should declare and define unsigned char array
to hold bitmap image in the global scope. I would strongly recommend
you to construct array class in your own. Declare unsigned char to
static const inside array class. In another way, you can use pointer
to unsigned char when it uses dynamic memory. You use fstream to
read / load raw bitmap image into dynamic memory. You can use either
choice.

For example:

// Header
class CFontImage
{
private:
static const unsigned char fonts[ 256 ] [ 8 * 8 ];
// or...
unsigned char *pFonts; // Load raw bitmap image

public:
// Write your member functions to maniuplate fonts
};

// Source code

const unsigned char CFontImage::fonts[ 256 ] [ 8 * 8 ] =
{
{....},
{....},
etc
};

The member function in the CFontImage class reads data from string
class and then range ASCII is selected in the fonts array before 8 x 8
font pixel is copied into surface class.

Very simple! Much easier to know where member functions belong to
CFontImage class rather than use global scope.
 
A

aku ankka

I agree with you.  You should declare and define unsigned char array
to hold bitmap image in the global scope.  I would strongly recommend
you to construct array class in your own.  Declare unsigned char to
static const inside array class.  In another way, you can use pointer
to unsigned char when it uses dynamic memory.  You use fstream to
read / load raw bitmap image into dynamic memory.  You can use either
choice.

Heap is heaps better for surface data. Global variables are rarely
needed at all and won't work very well on few mobile environments /
platforms (globals and statics are tricky on BREW and SYMBIAN).

I have abstraction for surfaces, where surface class is a reference
(not in C++ sense of the word) to the image data. The surface class
has a pointer to the image data, width, height, stride and format.

That is all information I need to communicate with different API's,
OpenGL; Direct3D, OpenCL and so on. The surface class is just
description of the image data, nothing more. Examples:

1. Create surface from a file

surface* s = surface::create(L"bukkake.jpg"´, pixelformat::argb8888);
uint32* image = s->lock<uint32>();
// TODO: do something with image
s->unlock();
s->release();

The pixelformat is complex object which describes the pixelformats
with masks for color components, has type enumeration for components
(uint32, float, half, etc..), fourcc for compressed data and so on and
on. The pixelformat::argb8888 is pre-defined format for convernience
(there are obviously more but that one is very common ;)

This approach reads the file, decodes the bitstream and creates a new
surface object. Pretty obvious. The surface "owns" the data, so the
release() method will deallocate the image.

2. Creating a reference to existing image..

void foo(char* image)
{
// we "know" that the raw data is in RGB565 format
surface* s = surface::create(320, 240, pixelformat::rgb565, image,
320 * sizeof(uint16));
// ... do something ..
s->release();
}

This time around the s->release WON'T free the image data, since this
surface is just describing (=reference) to data elsewhere.

What if we want to create a surface which DOES "own" the image data?

3. Create surface and allocate memory

surface* s = bitmap::create(640, 480, format);
s->release();

And so on. The "API" is same for the surfaces; you can lock them, read
and write to the image data the surface is describing, serialize
(write into file, memory buffer, etc.).. clear the surface, blit it to
other surface (with scaling, filtering, etc).

The surface system supports bitmaps, surfaces, cubemaps, 3d textures,
2d textures, you name it. The code is portable, however, I only have
tested it on OS X, Linux (32 bit and 64 bit), IRIX and Windows (32 bit
and 64 bit). So basically 32 bit and 64 bit, little and big endian
systems are covered.

The "system" might sound complicated, but it's not, really. Simple
inheritance to support different flavors of surfaces.

I have a font system as well, but it's based on textures and unicode
(can render different languages than just Latin). Latin is easy if we
use "char"; just use a look-up-table and we're done. Unicode requires
more eloborate caching scheme since we don't know in advance which
glyphs might be needed.

First, we need to cache the glygps.. for this I use a simple binary
tree for lookup. If we have a cache miss, we need to allocate texels
from existing texture. So we need a surface manager (2D memory
allocator). It's more efficient to use a single texture and spill the
least recently used glyphs out (so I use LRU eviction policy, sue me)
rathen than trying to use more textures.

The cache size (=texture size) is configurable, I usually am very
happy with 512x512 texture, but 2048x2048 would probably never spill
in practical application.

The surface manager does NOT have de-fragmenting, I use fixed tile
size which I determine from the font size. This wastes maybe 5-10% of
texture area but eliminates the need for de-fragmenting so it's a good
tradeoff.

If I were doing application just for Latin character set, a simple
lookup table approach would be much simpler. But I have to support
Japanese, Korean, etc. I don't know those languages, but filenames in
those languages MUST work in the User Interface which is rendered with
OpenGL, so, Unicode font system is a Must.

Speaking of unicode, supporting it with c++ is a bit .. let's not talk
about that.
 
J

James Kanze

If it says so, it is a bad book.

Or simply old. (Back when I was learning C++, all good books said to
be
sure to check the results of new for a null pointer. Back when I was
learning C++, there weren't exceptions.)
If new fails, standard behaviour is to throw std::bad_alloc. Some very
old compilers got that wrong, noticeably VC6.0.

Can't complain too much about VC6.0. It appeared before the standard,
at a time when it wasn't clear what the standard would require of
operator new. (It was fairly clear that an exception was in order,
but
IIRC, the name of the exception changed several times along the way.
And of course, most compilers before VC6.0 didn't throw an exception,
because they didn't support exceptions.)
If you use that compiler and can't change, you can change a setting to
make it standards-compliant in that respect.

For most applications, the most appropriate solution is probably to
set
the new_handler to abort the program with an error message.
Recovering
from out of memory can be tricky. (There are a number of exceptions,
of
course, but aborting in the case of insufficient memory is an
appropriate response for many applications. And is a lot simpler to
implement than any of the other choices.)
You do realize, that you are just creating a dumped-down version of
std::vector? So your class is useless if not as an exercise. Also, you
are missing a lot of stuff - an assignment operator and a copy
constructor needs to be written.
For example:
class array
{
public:
array( int size )
{
m_pArray = new int[ size ];
m_size = size;
if( m_pArray == 0 )
{
// Display Error Message -- out of memory
// Close other application and try again or
// use exit() function
This behaviour is better delegated into the new_handler function.

The behavior in comments, yes. Just setting the flag, no, but if
that's
really what is needed (which I doubt), then he needs to use
new(nothrow).
Prefer initialization rather than assignment. Your constructor should
be
array( int size ): m_size(size),m_pArray(new int[ size ]) {}
Also notice that m_bOutofMemory only gets initialised in case there is
a memory leak, so you are likely to run into undefined behaviour in
TestMemory.
There is no need for this check.
{
delete [] m_pArray;
m_pArray = 0;
And no need for this assignment.
That hungarian notation really creeps me out.

Real Hungarian can be useful, see
http://msdn.microsoft.com/en-us/library/aa260976(VS.60).aspx.
What
Simonyi describes, however, is not the Hungarian we generally see (nor
the Hungarian used above). In C++, too, it's generally better to go
one
step further, and create a class (a true type), rather than faking it
with an int and a prefix to the name. And in general, it's also
probably better to write the name out in full, rather than to use a
lot
of succinct abbreviations. (The important point in Simonyi's
Hungarian
is consistency, which is good, and the semantic value: a color is not
an
x coordonate, even if both are represented by an int. Both important
points for readable software.)
Why do you want to allocate a dynamically? This is just silly. Use
array a(5);
Why do you compare to true - this is just obfuscation. Prefer:
if( a->TestMemory() )
Here you have a memory leak - because of the dynamic allocation of a.

Technically, you can't have a memory leak if you're returning to the
system. The only way you can have a memory leak is to do something in
a
loop which fails to delete all the memory it allocates.
 
J

James Kanze

[...]
I build my own class. I don't need to use vector because I don't need
all the features such as search or insert element / remove element. I
suppose to put an assignment operator and a copy constructor to
private if I don't need to use them.

So? The question is: do you need some feature std::vector doesn't
provide, or is it important to ban some feature that it does provide
(as
opposed to just not using it)? If not, just use std::vector. And if
you do need to ban some feature (often wise), then you'll still use
std::vector in the implementation of your class.
For example:
class array
{
public:
array( int size )
{
m_pArray = new int[ size ];
m_size = size;
if( m_pArray == 0 )
{
// Display Error Message -- out of memory
// Close other application and try again or
// use exit() function
This behaviour is better delegated into the new_handler function.
Are you saying?

That you should set a new_handler (function std::set_new_handler), and
output the message and exit from it. Until you really know what you
are
doing, this is probably the best solution. (Even after you know what
you are doing, it's often the best solution.)

Note that even this may be trickier than it seems, since trying to
output a message may try to allocate dynamic memory. One solution
I've
frequently seen used is to pre-allocate a reserve buffer, which is
freed
first thing in the new handler. Alternatively, you can use setbuf on
std::cerr, or you can use system level output requests and static
buffers. (The latter solution is the most robust, but is not
portable.)
I create some classes to build different objects and put them into
memory. For example, 5 different classes are constructed successfully
and are stored in memory. They will be destructed after the program
exits successfully. If one class attempts to allocate more memory,
then bad allocation must be returned before new_handler exception is
thrown. Correct?

No. If you use a normal new (not placement) expression and don't
worry
about it. The basic algorithm of the operator new function is
required
to be:

void* result = attempt_to_allocate_memory();
while ( result == NULL )
{
(*current_new_handler)();
result = attempt_to_allocate_memory();
}
// Post-condition of loop: result != NULL !!!
return result;

The default new handler throws std::bad_alloc, but you can set it to
just about anything you want: the requirements are that it must do one
of three things:

-- make more memory available and return
-- throw std::bad_alloc or an exception derived from std::bad_alloc
-- exit the program (exit() or abort()).

(It may do more, e.g. log the fact that an error has occured, or
restore
the default new handler if it can't free up memory, for example.)
I do not need to test to find out if new keyword returns a pointer
with bad allocation.

A new expression always returns a valid pointer. If it returns.
For example:
int *a = new int [1000];
if( a == )
exit();
I should use new_handler instead, but I have to use test condition to
find out if a is already allocated.
For example:
int *a = new int [1000];
// Do something
// Are ready to terminate your program.
// I have to clean up to deallocate memory.

It's perfectly acceptable to "abort" a program without cleaning up
memory. Except in special cases, there are really only two
alternatives
for handling out of memory: set the new handler to terminate the
program, or catch std::bad_alloc at the highest level and exit with an
error message. (The latter may be preferable if e.g. the program uses
temporary files which will be deleted in destructors.) In either
case,
treat out of memory as a fatal error.
if( a != )
delete [] a;

If a is the result of a new expression, you can always delete it. If
a
is a null pointer, you can delete it as well. And if a is something
else, there's absolutely no way to test for it, so your program logic
must ensure that it's one of those. And you don't need the if, ever.
Please explain why you dislike hungarian notation.

Because it makes the code unmaintainable (and unreadable).
It provides you more information when you need to know because there
may be hundreds or thosuands of variables.

In one class? Thousands of member variables sounds like a design
error
to me.

More generally, while there may be any number of variables in the
entire
function, you should never deal with more than a few at a time. And
usually, whether a variable is an int or a long is less important than
whether it is an x coordinate, a color id, or a timestamp (and if it's
a
pointer, that will be immediately evident in the way it is used).
There's a reasonable argument for Hungarian as it was originally
designed (where information as to whether the variable was an
x-coordinate, a color-id or a timestamp was encoded), although even in
such cases, I find it better to avoid unpronounciable abbreviations,
and
in production code, at least, to define class types for each type,
rather than using int or long. (This is a perfect example of what I
mentionned at the start: banning some functionality. You don't want
to
support adding a timestamp to an x-coordinate, for example, but if
both
are int's, you do support it. And if you support subtraction of
timestamps, the result shouldn't be a timestamp, but an interval. So
you write a class, which uses int in its implementation, but only
supports the operations you want.)

[...]
Here is another good example.
#include <iostream>
using std::cerr;
using std::cout;
using std::endl;
#include <new>
using std::set_new_handler;
#include <cstdlib>
using std::abort;
using std::exit;
class array
{
public:
array( int size ) : m_size( size ), m_pLargeArray( new long long
[ size ] )
{
cout << "array::constructor -- count: " << ++s_ObjectCount << endl;
}
~array()
{
cout << "array::destructor -- count: " << s_ObjectCount-- << endl;
delete [] m_pLargeArray;
}
private:
long long *m_pLargeArray;
int m_size;

Why not simple
static int s_ObjectCount;
};
int array::s_ObjectCount = 0;
void customNewHandler()
{
cerr << "customNewHandler was called.\n";
cerr << "Display Error: Not enough Memory.\n\n";
cerr << "Your C++ project must be terminated." << endl;
// abort();
exit( EXIT_SUCCESS );
EXIT_SUCCESS?


int main()
{
set_new_handler( customNewHandler );
array a1( 50000000 ); // Success
array a2( 50000000 ); // Success
array a3( 50000000 ); // Success
array a4( 50000000 ); // Success
array a5( 50000000 ); // Failed -- bad memory allocation.
cout << "C++ project runs successful." << endl;
return 0;
}
If bad memory allocation is detected, then will exit() function does
its own responsibility to deallocate a1, a2, a3, and a4 from the
memory before program is terminated?

Once the program ceases to exist, it doesn't have any resources.
Unless
something is persistent (files, etc.), in a very real sense, it ceases
to exist. (This may not be true in a freestanding implementation.)
Once exit() is finished, your process doesn't exist, and has no memory
to be freed. (Physically, of course, the memory chips are still in
the
computer, and the OS will reuse them for something else. Just as it
will also clean up any more abstract resources your process was using:
file locks, mutex or semaphores, etc.)
Do you suggest me to put new_handler exception in main.cpp only?

If you're using a new handler, you should set it first thing in main.
(or even before, but that's somewhat trickier).
 
J

James Kanze

[...]
I hate signed integer on all sizes. I zlways use unsigned integer.

How do you represent negative values, then?

In addition, in C/C++, unsigned are very funny beasts, with very
special
semantics. I wouldn't use them in any context where "usual"
arithmetic
or comparison for inequality might be involved.
Often, strings use signed char or signed wchar_t. Combining unsigned
integer and signed integer are problemtic. I always declare unsigned
char to string because sometimes, I want to use between 128-256 range
ASCII or unicode.

It works in practice with char, although you do have to pay attention
in
some cases. Using an unsigned type for characters would be more
logical, but it doesn't work in C/C++ because everything expecting
characters uses char. So you're stuck using char, and working around
the problem areas.
I agree with you. You should declare and define unsigned char array
to hold bitmap image in the global scope.

A bitmap is something where an unsigned integral type is appropriate.
Depending on the context, I'd use unsigned char or unsigned int.
I would strongly recommend you to construct array class in your own.

What for?
Declare unsigned char to static const inside array class. In another
way, you can use pointer to unsigned char when it uses dynamic memory.

If you need buffers, std::vector< unsigned char > works very well.
Much
better than anything you could write yourself, probably.
You use fstream to read / load raw bitmap image into dynamic memory.
You can use either choice.
For example:
// Header
class CFontImage
{
private:
static const unsigned char fonts[ 256 ] [ 8 * 8 ];

I'm not sure about the static, and you certainly don't want const
(since
the data will almost certainly be read from disk).
// or...
unsigned char *pFonts; // Load raw bitmap image
public:
// Write your member functions to maniuplate fonts
};
// Source code
const unsigned char CFontImage::fonts[ 256 ] [ 8 * 8 ] =
{
{....},
{....},
etc

You don't reallly write that yourself. (But it does suggest the third
possibility: you generate this C++ code using some other program.)
The member function in the CFontImage class reads data from string
class and then range ASCII is selected in the fonts array before 8 x 8
font pixel is copied into surface class.
Very simple! Much easier to know where member functions belong to
CFontImage class rather than use global scope.

Certainly. No one is saying that you shouldn't have application level
classes. Just that it's a waste of time to reimplement the logic of
std::vector.
 
P

peter koch

Or simply old.  (Back when I was learning C++, all good books said to
be
sure to check the results of new for a null pointer.  Back when I was
learning C++, there weren't exceptions.)

Right. But in that case it is still a bad book even though it might
have been excellent when published.
Can't complain too much about VC6.0.  It appeared before the standard,
at a time when it wasn't clear what the standard would require of
operator new.  (It was fairly clear that an exception was in order,
but
IIRC, the name of the exception changed several times along the way.
And of course, most compilers before VC6.0 didn't throw an exception,
because they didn't support exceptions.)

I agree: my statement was not meant to degrade VC6.0, but rather to
help the OP in case he still uses that old compiler. I believe VC6.0
is the only still used compiler where new does not throw.
For most applications, the most appropriate solution is probably to
set
the new_handler to abort the program with an error message.
Recovering
from out of memory can be tricky.  (There are a number of exceptions,
of
course, but aborting in the case of insufficient memory is an
appropriate response for many applications.  And is a lot simpler to
implement than any of the other choices.)
I would prefer a std::bad_alloc exception in the normal case which (if
I remember correctly) a compiler switch can fix.
array class is already constructed before dynamic memory is tested.
If it fails, error message is displayed before exit() function
terminates the program.  If I decide to allow the program running
after dynamic memory reported out of memory, then array class should
use destructor to clean up all data members and release array class
from the memory.
You do realize, that you are just creating a dumped-down version of
std::vector? So your class is useless if not as an exercise. Also, you
are missing a lot of stuff - an assignment operator and a copy
constructor needs to be written.
For example:
class array
{
public:
        array( int size )
        {
                m_pArray = new int[ size ];
                m_size = size;
                if( m_pArray == 0 )
                {
                        // Display Error Message -- out of memory
                        // Close other application and try again or
                        // use exit() function
This behaviour is better delegated into the new_handler function.

The behavior in comments, yes.  Just setting the flag, no, but if
that's
really what is needed (which I doubt), then he needs to use
new(nothrow).




                        // if( yes )
                        // exit();
                        // else ( no and continue )
                        m_bOutofMemory = true;
                        return;
                }
        }
Prefer initialization rather than assignment. Your constructor should
be
        array( int size ): m_size(size),m_pArray(new int[ size ]) {}
Also notice that m_bOutofMemory only gets initialised in case there is
a memory leak, so you are likely to run into undefined behaviour in
TestMemory.
        ~array()
        {
                if( m_pArray != 0 )
There is no need for this check.
                {
                        delete [] m_pArray;
                        m_pArray = 0;
And no need for this assignment.
                }
        }
        bool TestMemory()
        {
                return m_bOutofMemory;
        }
private:
        int m_size;
        int *m_pArray;
        bool m_bOutofMemory;
That hungarian notation really creeps me out.

Real Hungarian can be useful, seehttp://msdn.microsoft.com/en-us/library/aa260976%28VS.60%29.aspx.
What
Simonyi describes, however, is not the Hungarian we generally see (nor
the Hungarian used above).  In C++, too, it's generally better to go
one
step further, and create a class (a true type), rather than faking it
with an int and a prefix to the name.  And in general, it's also
probably better to write the name out in full, rather than to use a
lot
of succinct abbreviations.  (The important point in Simonyi's
Hungarian
is consistency, which is good, and the semantic value: a color is not
an
x coordonate, even if both are represented by an int.  Both important
points for readable software.)




Why do you want to allocate a dynamically? This is just silly. Use
        array a(5);
Why do you compare to true - this is just obfuscation. Prefer:
        if( a->TestMemory() )
Here you have a memory leak - because of the dynamic allocation of a.

Technically, you can't have a memory leak if you're returning to the
system.  The only way you can have a memory leak is to do something in
a
loop which fails to delete all the memory it allocates.

Technically, you're right, but my understanding is that main simply
was a means to demonstrate usage of the class. From that point of
view, there is indeed a memory leak.

/Peter
 
J

James Kanze

Right. But in that case it is still a bad book even though it might
have been excellent when published.

I'm not sure I agree. I'm not familiar with Deitel, so I can't say
one
way or another, but the Barton and Nackman is still a very good book,
despite its age. How new handles out of memory is, after all, really
a
detail when compared to many other issues. (On the other hand, if the
book was written before exceptions, one might wonder about its
treatment
of exception safety. Which isn't just a detail.)

[...]
I would prefer a std::bad_alloc exception in the normal case which (if
I remember correctly) a compiler switch can fix.

I'm of two minds about this. On one hand, *if* all you're going to do
is abandon, then you might as well do it in the new_handler, and
ignore
the issue everywhere else. Knowing that allocation can't raise an
exception makes exception safety easier (since many more functions are
no throw). On the other hand, running out of memory isn't really a
program error like violating a precondition invariant, and you know
enough about the program state that it should be safe to execute the
destructors. Some of which might free up persistent resources, like
temporary files.

[...]
Technically, you're right, but my understanding is that main simply
was a means to demonstrate usage of the class. From that point of
view, there is indeed a memory leak.

It's hard to say. If he put the code in main in a loop, yes, there
would be a memory leak. But of course, if you're thinking about the
total program, rather than just demonstrating usage of the class,
you're
likely to think about the delete anyway. (Of course, in real code,
you'd never allocate this type of object dynamically anyway, so the
problem is moot.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,999
Messages
2,570,246
Members
46,842
Latest member
MableIwk73

Latest Threads

Top