Home > Archive > VC Language > May 2006 > Re: True/False: As of VC 6.0, with MS compilers, usage of new(noth
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Re: True/False: As of VC 6.0, with MS compilers, usage of new(noth
|
|
| ultranet 2006-05-24, 7:10 pm |
|
"Alex Blekhman" wrote:
> ultranet wrote:
>
> The real question is: why do you need `new(nothrow)' at all?
> What does it buy you to undergo all these troubles?
It's easier to code than try-catch.
Anyway, it appears if one knows that constructor doesn't throw, then it's OK
to use new(nothrow) even in vc 6.0. But if constructor does throw, one has to
use regular new.
However, i only found a new macro for _DEBUG:
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
But i was getting build error w/ new(nothrow) even in release mode. What am
i missing?
So all VS VC++ projects should support new(nothrow) by default?
| |
| Igor Tandetnik 2006-05-24, 7:10 pm |
| ultranet <ultranet@discussions.microsoft.com> wrote:
> However, i only found a new macro for _DEBUG:
>
> But i was getting build error w/ new(nothrow) even in release mode.
Show the error message and the line of code it relates to. Do you
#include <new> ? That's where 'nothrow' symbol is defined.
--
With best wishes,
Igor Tandetnik
With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
| |
| ultranet 2006-05-24, 7:10 pm |
|
"Igor Tandetnik" wrote:
> ultranet <ultranet@discussions.microsoft.com> wrote:
>
> Show the error message and the line of code it relates to. Do you
> #include <new> ? That's where 'nothrow' symbol is defined.
Actually, i was able to use it in another project, which i think was started
as a consolde project, and then Shared MFC was added in project settings.
But in this one, that was started as MFC, i get this:
#include <new>
using namespace std;
pMy = new(nothrow) MyClass(...);
........cpp(78) : error C2665: 'new' : none of the 3 overloads can convert
parameter 2 from type 'const struct std::nothrow_t'
| |
| Igor Tandetnik 2006-05-24, 7:10 pm |
| ultranet <ultranet@discussions.microsoft.com> wrote:
> #include <new>
>
> using namespace std;
>
> pMy = new(nothrow) MyClass(...);
>
> .......cpp(78) : error C2665: 'new' : none of the 3 overloads can
> convert parameter 2 from type 'const struct std::nothrow_t'
Quote the full error message. Error C2665 usually lists the overloads
that were considered by the compiler.
Does MyClass have a class-specific operator new, by any chance?
--
With best wishes,
Igor Tandetnik
With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
| |
| ultranet 2006-05-24, 7:10 pm |
|
"Igor Tandetnik" wrote:
> Quote the full error message. Error C2665 usually lists the overloads
> that were considered by the compiler.
Nope, that's it.
> Does MyClass have a class-specific operator new, by any chance?
Bingo, it's a CDialog subclass, and CObject overrides new. I'm not sure i
want to mess w/ adding an operator to my class though.
At the same time, ::new(nothrow) produces a warning, based on what i've
mentioned before:
MyClass.cpp(78) : warning C4291: 'void *__cdecl operator new(unsigned
int,const struct std::nothrow_t &)' : no matching operator delete found;
memory will not be freed if initializa
tion throws an exception
C:\Program Files\Microsoft Visual Studio\VC98\INCLUDE\new(36) : see
declaration of 'new'
I'm thinking about adding a pragma to ignore the warning maybe, but probably
will just take a note, and use try-catch for these kinds of classes.
| |
| Igor Tandetnik 2006-05-24, 7:10 pm |
| ultranet <ultranet@discussions.microsoft.com> wrote:
> "Igor Tandetnik" wrote:
>
> Nope, that's it.
> Bingo, it's a CDialog subclass, and CObject overrides new. I'm not
> sure i want to mess w/ adding an operator to my class though.
>
> At the same time, ::new(nothrow) produces a warning, based on what
> i've mentioned before:
> MyClass.cpp(78) : warning C4291: 'void *__cdecl operator new(unsigned
> int,const struct std::nothrow_t &)' : no matching operator delete
> found; memory will not be freed if initializa
> tion throws an exception
> C:\Program Files\Microsoft Visual Studio\VC98\INCLUDE\new(36)
> : see declaration of 'new'
>
> I'm thinking about adding a pragma to ignore the warning maybe, but
> probably will just take a note, and use try-catch for these kinds of
> classes.
If I recall correctly, in VC6 operator new does not throw bad_alloc
anyway, but always returns NULL when memory allocation fails. So I
suspect the whole issue is moot. You can test it with something like
char* p = new char[0x7FFFFFFF];
and see if you get an exception, or a NULL pointer.
--
With best wishes,
Igor Tandetnik
With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
| |
| Jason Doucette 2006-05-24, 7:10 pm |
| > If I recall correctly, in VC6 operator new does not throw bad_alloc
> anyway, but always returns NULL when memory allocation fails.
Yup.
Don't Let Memory Allocation Failures Crash Your Legacy STL Application
http://msdn.microsoft.com/msdnmag/i...ix/default.aspx
"The default behavior of operator new in all versions of Visual C++ through
version 6.0 is to return NULL rather than throw an exception when it fails."
--
Jason Doucette / Xona.com
www.jasondoucette.com / www.xona.com
| |
| ultranet 2006-05-24, 7:10 pm |
|
"Jason Doucette" wrote:
>
> Yup.
>
> Don't Let Memory Allocation Failures Crash Your Legacy STL Application
> http://msdn.microsoft.com/msdnmag/i...ix/default.aspx
>
> "The default behavior of operator new in all versions of Visual C++ through
> version 6.0 is to return NULL rather than throw an exception when it fails."
>
I tried to reproduce this, but it hung my CPU, so i gave up for now.
So are we to conclude that?
a. use try-catch per standard and blame M$ before VC .NET.
b. have a try-catch and a != NULL check for passivity w/ VC 6.0 and below.
| |
| ultranet 2006-05-24, 7:10 pm |
|
"ultranet" wrote:
> So are we to conclude that?
> a. use try-catch per standard and blame M$ before VC .NET.
> b. have a try-catch and a != NULL check for passivity w/ VC 6.0 and below.
>
Whether it's a., or b., i tried this too:
new(nothrow) vector<long>(nCnt);
It built in Release, but not in Debug in that MFC project. Given that i
don't feel like messing w/ new macros, i think i'm making a rule for myself
to not use new(nothrow) in MFC projects. When those macros aren't defined,
i'll consider using it, but it appears it's all exacerbates by the lack of
standard compliance. I'll try to read the article mentioned in full, and see
if there are any better alternatives than b.
| |
| Igor Tandetnik 2006-05-24, 7:10 pm |
| ultranet <ultranet@discussions.microsoft.com> wrote:
> It built in Release, but not in Debug in that MFC project. Given that
> i don't feel like messing w/ new macros, i think i'm making a rule
> for myself to not use new(nothrow) in MFC projects. When those macros
> aren't defined, i'll consider using it, but it appears it's all
> exacerbates by the lack of standard compliance. I'll try to read the
> article mentioned in full, and see if there are any better
> alternatives than b.
Note also that defining a keyword as a macro is in and of itself a
violation of the standard:
17.4.3.1.1/2 A translation unit that includes a [standard library - IT]
header shall not contain any macros that define names declared or
defined in that header. Nor shall such a translation unit define macros
for names lexically identical to keywords.
I believe MFC Wizard continues to generate this abomination in all
versions of VC up to and including VC8.
--
With best wishes,
Igor Tandetnik
With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
| |
| ultranet 2006-05-25, 7:08 pm |
| "ultranet" wrote:
> It built in Release, but not in Debug in that MFC project. Given that i
> don't feel like messing w/ new macros, i think i'm making a rule for myself
> to not use new(nothrow) in MFC projects. When those macros aren't defined,
> i'll consider using it, but it appears it's all exacerbates by the lack of
> standard compliance. I'll try to read the article mentioned in full, and see
> if there are any better alternatives than b.
Reproduced it:
char* cArray = NULL;
try {
cArray = new char[3500000000];
cout << "array == " << (unsigned int)cArray << endl;
} catch(bad_alloc&) {
cerr << "bad_alloc" << endl;
}
cout << "Done!" << endl;
Getting 0.
OK, new rule for myself:
1. if code has potential for being cross-platform, use try-catch, and if
code is to be built w/ pre-.NET libraries for Windows, preferrably also check
for NULL, at least until VC .NET libraries are adopted for building.
2. if code is Windows-specific, and if code is to be built w/ pre-.NET
libraries for, preferrably, only check for NULL, at least until VC .NET
libraries are adopted for building.
| |
| ultranet 2006-05-25, 7:08 pm |
|
"ultranet" wrote:
>
> OK, new rule for myself:
I)
> 1. if code has potential for being cross-platform, use try-catch, and if
> code is to be built w/ pre-.NET libraries for Windows, preferrably also check
> for NULL, at least until VC .NET libraries are adopted for building.
Acutally, rule #2 would be:
2. if code is Windows-specific, follow rule 1.
3. if code is specific to non-Windows platforms, only use try-catch.
II)
Alternative: overwriting new:
After reading
http://msdn.microsoft.com/msdnmag/i...ix/default.aspx
in full, it appears it has 2 limitations, that have to do w/ 3rd-party
dynamic libraries:
i. The fix for operator new(std:nothrow) is only required if new is changed
to throw an exception, a change that is mandatory for using STL correctly.
However, the fix is local to the project into which the source file is
inserted. In this case, any third-party DLL that uses operator
new(std::nothrow) and builds against a compatible release runtime DLL as I've
shown will now be at the peril of new(std::nothrow), throwing an exception on
failure.
ii. The final gotcha is that the STL provided with Visual C++ 6.0 does in
fact use this overload in a single place, namely the get_temporary_buffer
template function. It is quite unlikely that your code calls this function
directly. However, a search through the STL source code shows that the
internal _Temp_iterator template class calls the get_temporary_buffer
template function. The _Temp_iterator template class itself is called,
indirectly, by the following public functions defined in algorithm:
stable_partition, stable_sort, and inplace_merge. The behavior of these
functions is undefined if operator new(std::nothrow) does throw an exception.
If you are using these functions and you have the new handler installed,
consider using a different implementation of the STL, many of which are
available. I successfully use STLPort (http://www.stlport.org) in my work.
As far as i understand, neither i. nor ii. applies to the local project, but
could mess up otherwise working 3rd-party libraries built with pre-.NET VC.
Now that's a puzzle one can't get out of: do you use rules like in I), or
II), despite i. and ii.? It appears w/ II) you are still screwed sometimes,
cause 3rd-parties could crash. I), appears to be the most reliable, but would
require redundant code until upgrade to VC .NET.
Please vote for I) or II).
| |
| ultranet 2006-05-26, 4:13 am |
| "ultranet" wrote:
> Please vote for I) or II).
>
Actually, the article said the pre-.NET new(nothrow) throws anyway in
Release mode. Therefore, II) doesn't make things any worse than they already
are.
I'm inclined to conclude that option II) (overriding new and new(nothrow))
is the way to go. Any other opinions?
| |
| ultranet 2006-05-26, 7:09 pm |
|
"ultranet" wrote:
> "ultranet" wrote:
>
> Actually, the article said the pre-.NET new(nothrow) throws anyway in
> Release mode. Therefore, II) doesn't make things any worse than they already
> are.
Nope, i was right the first time: II) introduces issues i) and ii). So both
solutions are partial:
I) doesn't fix STL craashes.
II) causes i) and ii).
There should probably also be a 3rd option:
III) write standard-compliant code, and let blame Microsoft until VC .NET is
adopted.
I'm at III) now, and thinking if i need to switch to I) or II).
Any thoughts?
| |
| ultranet 2006-05-30, 7:15 pm |
|
"ultranet" wrote:
>
>
> "ultranet" wrote:
>
> Nope, i was right the first time: II) introduces issues i) and ii). So both
> solutions are partial:
> I) doesn't fix STL craashes.
> II) causes i) and ii).
> There should probably also be a 3rd option:
> III) write standard-compliant code, and let blame Microsoft until VC .NET is
> adopted.
>
> I'm at III) now, and thinking if i need to switch to I) or II).
There's also IV:
IV) introduce project-and-IDE-version-specific macros to fix MS new
(although this violates standards, it fixes original l standard violations
w/o causing subtle issues like i), and ii), and it will have no effect in IDE
version where issue is resolved).
|
|
|
|
|