From: mrs@cygnus.com (Mike Stump)
Subject: Re:  g++ 2.2.2 runs constructor even if operator new() returns 0
Organization: GNUs Not Usenet
Distribution: gnu
Date: Fri, 4 Sep 1992 21:50:54 GMT

This behavior is under consideration by the ANSI C++ committee, they
are thinking about defining things such that new should never return
0.  It would throw an exception instead.  This has long been recognized
by g++ as the proper way to do things, and hence its past and current
behavior.

I am inclided not to consider this a bug, until ANSI C++ decides it is.

For now, I would recommend that you try and code your software in such
a way that it will work or be easy to change, either way ANSI decides.

As a practical matter, you can do something like:

  p = (void *) malloc (sz);
  if (p == 0)
    (*__new_handler) ();
  return p;

in your g++ operator new code.

> Message-Id: <1992Jul21.191511.2772@jade.ab.ca>
> From: earl@jade.ab.ca (Earl Locken)
> To: bug-g++@prep.ai.mit.edu
> Date: Tue, 21 Jul 1992 19:15:11 GMT
> Organization: Jade Simulations International, Inc.

>     g++ executes the constructor if the operator new defined for the
> class returns 0.  The ARM, page 61, says:

> 	... initialization is done only if the value returned by
> 	the operator new() is nonzero.  If the value returned by 
> 	the operator new() is 0 (the null pointer) the value of
> 	the expression is 0.

>      Sun CC (and, I would assume, all cfront-based compilers) does not
> call the constructor.  This seems to be much preferable to having to
> have each constructor check for a NULL this.

>      Here's a little test program that shows that g++ runs the
> constructor if new() returns 0.

> #include <stdio.h>
> #include <stddef.h>

> class atype {
>  public:
> 	atype();
> 	void *operator new(size_t size) { return 0; };
> 	void *operator new(size_t size, int alloc_size) { return 0; };
> 	void operator delete(void *block) { };
> 	};

> atype::atype()
> {
> 	if (this == 0)
> 		printf("atype:atype() constructor run illegally\n");
> }

> main()
> {
> 	atype *x = new atype;
> 	if (x) delete x;
> }

>      Here is the cpp-processed version.

> g++ -E null-new.C
> # 1 "null-new.C"
>  
>  
>  
>  
>  
>  
>  
>  

> # 1 "/usr/local/lib/g++-include/stdio.h" 1 3
>  
>  
















>  


























> #pragma interface







>  
>  
>  









> # 82 "/usr/local/lib/g++-include/stdio.h" 3


> extern "C" {





























> # 1 "/usr/local/lib/gcc-lib/sun3-sunos4.1.1/2.2.2a/include/stdio.h" 1 3
>  




> extern	struct	_iobuf {
> 	int	_cnt;
> 	unsigned char *_ptr;
> 	unsigned char *_base;
> 	int	_bufsiz;
> 	short	_flag;
> 	char	_file;		 
> } _iob[];








































> extern struct _iobuf 	*__hide_fopen ();
> extern struct _iobuf 	*__hide_fdopen ();
> extern struct _iobuf 	*__hide_freopen ();
> extern struct _iobuf 	*__hide_popen ();
> extern struct _iobuf 	*tmpfile();
> extern long	ftell();
> extern char	*fgets();
> extern char	*gets();
> extern char	*__hide_sprintf ();
> extern char	*ctermid();
> extern char	*cuserid();
> extern char	*__hide_tempnam ();
> extern char	*tmpnam();






> # 114 "/usr/local/lib/g++-include/stdio.h" 2 3































> }





> extern "C" {







> int    _doprnt(const char*, void*, struct _iobuf *);
> int    _doscan(struct _iobuf *, const char*, ...);
> int    _filbuf(struct _iobuf *);
> int    _flsbuf(unsigned, struct _iobuf *);


> int    fclose(struct _iobuf *);
> struct _iobuf *  fdopen(int, const char*);
> int    fflush(struct _iobuf *);
> int    fgetc(struct _iobuf *);
> char*  fgets(char*, int, struct _iobuf  *);
> struct _iobuf *  fopen(const char*, const char*);
> int    fprintf(struct _iobuf *, const char* ...);
> int    fputc(int, struct _iobuf *);
> int    fputs(const char*, struct _iobuf *);
> int fread(void*, int, int, struct _iobuf *);



> struct _iobuf *  freopen(const char*, const char*, struct _iobuf *);

> int    fscanf(struct _iobuf *, const char* ...);
> int    fseek(struct _iobuf *, long, int);
> long   ftell(struct _iobuf  *);
> int fwrite(const void*, int, int, struct _iobuf *);
> char*  gets(char*);
> int    getw(struct _iobuf *);
> int    pclose(struct _iobuf *);
> void   perror(const char*);
> struct _iobuf *  popen(const char*, const char*);
> int    printf(const char* ...);
> int    puts(const char*);
> int    putw(int, struct _iobuf *);
> int    rewind(struct _iobuf *);
> int    scanf(const char* ...);
> int    setbuf(struct _iobuf *, char*);
> int    setbuffer(struct _iobuf *, char*, int);
> int    setlinebuf(struct _iobuf *);
> int    setvbuf(struct _iobuf *, char*, int, int);
> int    sscanf(char*, const char* ...);
> struct _iobuf *  tmpfile();
> int    ungetc(int, struct _iobuf *);
> int    vfprintf(struct _iobuf *, const char*, ...);

>  
>  

> int    vprintf(const char*, ... );





> char*  sprintf(char*, const char*, ...);
> char*  vsprintf(char*, const char*, ...);


> }


















> # 10 "null-new.C" 2

> # 1 "/usr/local/lib/g++-include/stddef.h" 1 3


> extern "C" {



> # 1 "/usr/local/lib/gcc-lib/sun3-sunos4.1.1/2.2.2a/include/stddef.h" 1 3



>  









>  


>  





>  


















>  


> typedef int ptrdiff_t;









>  


>  




















>  


> typedef int size_t;












>  





















>  


> typedef short unsigned int wchar_t;












>  









>  






> # 7 "/usr/local/lib/g++-include/stddef.h" 2 3




> }

> # 11 "null-new.C" 2


> class atype {
>  public:
> 	atype();
> 	void *operator new(size_t size) { return 0; };
> 	void *operator new(size_t size, int alloc_size) { return 0; };
> 	void operator delete(void *block) { };
> 	};

> atype::atype()
> {
> 	if (this == 0)
> 		printf("atype:atype() constructor run illegally\n");
> }

> main()
> {
> 	atype *x = new atype;
> 	if (x == 0) printf("x was 0");
> 	if (x) delete x;
> }


> -- 
> Earl Locken						earl@jade.ab.ca
> Jade Simulations International



Newsgroups: gnu.g++.bug