Discussion:
memory allocation error
(too old to reply)
Sudesh
2008-01-29 13:22:47 UTC
Permalink
Hello

Whats happening with the following code?

I have a class FOO.

FOO *foo;
int Index_Count = 3000;
try
{
foo = new FOO[Index_Count];
}
catch(Exception & E)
{
MessageDlg("Error in Program: " + E.Message, mtError, TMsgDlgButtons()
<< mbOK, 0);
}

There is no exception, means memory allocation is successful. correct?

Now when I try to set value for a member at an index 400, foo[400].member1,
I get an error.

In debug mode foo[400].memb1 shows "????"

Whats going wrong?

Thanks,
Sudesh
Asger Joergensen
2008-01-29 13:29:26 UTC
Permalink
Hi Sudesh
Post by Sudesh
Hello
Whats happening with the following code?
I have a class FOO.
FOO *foo;
int Index_Count = 3000;
try
{
foo = new FOO[Index_Count];
}
catch(Exception & E)
{
MessageDlg("Error in Program: " + E.Message, mtError, TMsgDlgButtons()
<< mbOK, 0);
}
There is no exception, means memory allocation is successful. correct?
Now when I try to set value for a member at an index 400, foo[400].member1,
I get an error.
What is the Error message ?

Kind regards
Asger
Sudesh
2008-01-29 17:17:49 UTC
Permalink
Hi Asger

EAccessViolation error.
Why do I get this when memory allocation is successful ( i mean, no
exception is raised at that point).

Thanks
Sudesh
Post by Asger Joergensen
Hi Sudesh
What is the Error message ?
Kind regards
Asger
Clayton Arends
2008-01-29 17:38:56 UTC
Permalink
Post by Sudesh
EAccessViolation error.
Why do I get this when memory allocation is successful ( i mean, no
exception is raised at that point).
You're going to have to show some more of your code. From what you've shown
this AV shouldn't be happening. It could be that the allocation hasn't
happened yet and you are accessing uninitialized data. Or, you could be
destroying the memory. Or, you could be overwriting the memory somewhere
else. Or, the class might not be initializing that data member. There are
many other possibilities.

Clayton
Chris Uzdavinis (TeamB)
2008-01-29 17:49:18 UTC
Permalink
Post by Sudesh
Hi Asger
EAccessViolation error.
Why do I get this when memory allocation is successful ( i mean, no
exception is raised at that point).
Something is still wrong. Yes, it shouldn't be a memory allocation
failure. Note that when you catch Exception& you are only catching
VCL exceptions and nothing else. C++ does not normally throw anything
but C++ exceptions, so I'm assuming that your FOO objects are
implemented using (or interacting with) VCL? Otherwise there is no
hope of ever catching an exception in your catch, but you will miss
any C++ exceptions like std::bad_alloc, if that's what's thrown.



FOO *foo;
int Index_Count = 3000;
try
{
foo = new FOO[Index_Count];
}
catch(Exception & E)
{
MessageDlg("Error in Program: " + E.Message, mtError,
TMsgDlgButtons() << mbOK, 0);
}


Could you show the declaration of FOO? How large are the instances?
Does the constructor do anything interesting to initialize itself? is
member1 a data member or a property, and if it's a property, does it
calla function that may be doing something bad?

Note that sometimes memory allocations from operating systems report
optimistic results. Due to the ability to page memory, if the OS
doesn't actually have the memory available when you ask for it, it may
still say that the allocation succeeded on the assumption that it may
become available later and/or you might not use it all.

In those cases, you can get a pointer returned that causes the OS to
try to find memory when you dereference it, and when that fails you
crash. This is how linux behaves, but I'm not sure if Windows is the
same or not.

(For details, Herb Sutter's article: http://www.ddj.com/cpp/184401393)

Unless FOO objects are heinously large, 3000 elements probably isn't
enough to cause new to fail. Occam's razor would suggest that
something is wrong in FOO's constructor, or possibly in the setter
function associated with member1 (if it's a property).

Please show your entire minimal program that reproduces this code.
Thanks.
--
Chris (TeamB);
Remy Lebeau (TeamB)
2008-01-29 17:56:46 UTC
Permalink
Post by Sudesh
catch(Exception & E)
'new' and 'new[]' do not throw an exception type that is derived from the
VCL's Exception class. If they were to fail, the above code would not be
able to catch it. They will throw a std::bad_alloc exception instead.
Post by Sudesh
There is no exception, means memory allocation is successful. correct?
By default, yes. However, if set_new_handler(0) is called, then 'new' will
return NULL instead of throwing an exception.
Post by Sudesh
Now when I try to set value for a member at an index 400,
foo[400].member1, I get an error.
You did not show what FOO is declared as, or say what the actual error is.


Gambit
Wayne A. King
2008-03-04 00:54:34 UTC
Permalink
On Tue, 29 Jan 2008 09:56:46 -0800, "Remy Lebeau \(TeamB\)"
Post by Remy Lebeau (TeamB)
if set_new_handler(0) is called, then 'new' will
return NULL instead of throwing an exception.
This is a month late as I just read this thread today,
but I'll comment for the benefit of any other latecomers.

set_new_handler(0) will only cause the nothrow version of new
to return a NULL pointer.

std::set_new_handler(0);
int *ptr
:
:
ptr = new int[INT_MAX]; // will still throw an exception
:
:
ptr = new(std::nothrow)int[INT_MAX]; // will return NULL

- Wayne

- Wayne A. King
***@idirect.com

Sudesh
2008-02-04 05:25:46 UTC
Permalink
Hello Everybody:

Thanks for your replies and sorry for my late reply. Let me explain in
detail.

FOO consists of a few array members (about 18) with about 20000 elements
each (double type) and rest are int,float,double type members. no member
functions though.

#define DATA_POINTS 20000

class FOO
{
public:
double A[DATA_POINTS];
double B[DATA_POINTS];
double C[DATA_POINTS];
double D[DATA_POINTS];
......
int a;
int b;
float c;
double d;
....
}

Size of class FOO instance is 1840528.

This is what I am trying:

FOO *foo;
int Index_Count = 3000;
try
{
foo = new FOO[Index_Count];

for (int index = 0; index < Index_Count; index++)
FOO[index].a = 1; // error at index 400

}
catch(Exception & E)
{
MessageDlg("Error in Program: " + E.Message, mtError, TMsgDlgButtons()
<< mbOK, 0);
}

After memory allocation, I get a memory pointer. So I thought allocation is
successful.

But with Index_Count=3000, exception is thrown in loop at line
FOO[index].a = 1 at index value about 400.
If I reduce Index_Count=2000, I can go for higher index value.

In debug window, value FOO[index].a shows "????" for index raising
exception. Lower values shows 0.

1. Please tell me how to catch memory allocation exception in this case.
2. I have 2 GB RAM. Is paging done if my FOO requires more RAM?

Thanks,
Sudesh
Clayton Arends
2008-02-04 05:59:50 UTC
Permalink
Post by Sudesh
FOO *foo;
int Index_Count = 3000;
try
{
foo = new FOO[Index_Count];
[snip]

That new[] is attempting to allocate over 5GB of data. In a 32-bit world
that is not possible with this direct approach. Unless there is a real
reason that you need that much data in memory at the same time I seriously
suggest a redesign.
Post by Sudesh
After memory allocation, I get a memory pointer. So I thought allocation
is successful.
If your "for" loop is being reached then under normal conditions that means
the allocation was successful. However, as Remy stated there are conditions
when custom allocation code can perform logic that is different than
expected.
Post by Sudesh
1. Please tell me how to catch memory allocation exception in this case.
As Remy and Chris pointed out you must capture the std::bad_alloc exception.
It is declared in new.h:

#include <new.h>
//...
try
{
//...
}
catch (std::bad_alloc const& e)
{
}
Post by Sudesh
2. I have 2 GB RAM. Is paging done if my FOO requires more RAM?
No. There might be ways of getting 3GB RAM. I am not a page file or memory
allocation expert but I believe a single Win32 application is limited to
2-3GB of memory. If you need more memory then you will need to swap your
data structures to disk yourself.

Clayton
Chris Uzdavinis (TeamB)
2008-02-04 14:26:11 UTC
Permalink
Post by Sudesh
Size of class FOO instance is 1840528.
FOO *foo;
int Index_Count = 3000;
try
{
foo = new FOO[Index_Count];
for (int index = 0; index < Index_Count; index++)
FOO[index].a = 1; // error at index 400
}
Given that each object is about 1.75MB in size, and you're trying to
allocate 3000 of them, simple math would require your system to have
about 5.14 GB of RAM.

How can you address 5.14 Gigabytes of RAM with a standard 4-byte
pointer? With 4 bytes (32-bits) you only get 2^32 possible values,
which is 4,294,967,296, or about 4.3 GB. Clearly, you cannot possibly
store an address spanning 5.14 GB of RAM in a pointer that can only
addres 4.3 GB. It's just too big.

You are going to have to partition your program up so that it only is
working on a subset of your data at any given time, and the rest is
either swapped out to disk, or recalculated as needed.
--
Chris (TeamB);
Clayton Arends
2008-02-04 17:31:11 UTC
Permalink
Post by Chris Uzdavinis (TeamB)
With 4 bytes (32-bits) you only get 2^32 possible values,
which is 4,294,967,296, or about 4.3 GB.
Do you work for a hard drive manufacturer? ;-)

Conventional base-2 calculation:

2^32 = 4,294,967,296 = 4GB

Hard drive manufacturer base-10 calculation:

1,000,000,000 = 1GB
times 4 = 4,000,000,000 = 4GB
4,294,967,296 = approx 4.3GB

Clayton
Chris Uzdavinis (TeamB)
2008-02-04 18:20:39 UTC
Permalink
Post by Clayton Arends
Post by Chris Uzdavinis (TeamB)
With 4 bytes (32-bits) you only get 2^32 possible values,
which is 4,294,967,296, or about 4.3 GB.
Do you work for a hard drive manufacturer? ;-)
2^32 = 4,294,967,296 = 4GB
1,000,000,000 = 1GB
times 4 = 4,000,000,000 = 4GB
4,294,967,296 = approx 4.3GB
You're right, of course. The difference doesn't change my conclusion
one bit, but it does show my attention was elsewhere while writing
that post. (I simply moved the decimal point rather than thinking of
the conversion rate given the units.)
--
Chris (TeamB);
Continue reading on narkive:
Loading...