Thread View: comp.std.c++
5 messages
5 total messages
Started by Alfredo V. Mendoza
Fri, 13 Oct 1995 02:00
overloading global new and delete
Author: Alfredo V. Mendoza
Date: Fri, 13 Oct 1995 02:00
Date: Fri, 13 Oct 1995 02:00
153 lines
4552 bytes
4552 bytes
Hello all,
The program below was a testcase sent to IBM compiler defect group.
The problem is when compiled with IBM (413) xlC 3.1.2 , and ran
the result is that the str() function in ostrstream does NOT use
the overloaded new but uses the IBM runtime new. And when the class
is destroyed the memory that was allocated by str() is deleted by the
user defined global delete. Which (IMHO) is wrong.
IBM compiler development claims that when one uses their runtime
classes, it will always use the IBM runtime new and delete regardless
of an overloaded global new and delete.
Unfortunately as this program shows if we follow the logic above
a mismatch will occur.
This program behaves differently from SUN solaris.
I have searched different C++ references and standards books but
I could not find anything that will tell/show how overloading
new and delete globally should be implemented. Hence I cannot
show IBM that their implementation is wrong.
QUESTION:
1. Does anyone know if there are any new standards that can point
to a correct implementation?
the output I get is :
****************************************
new(148) : signpost = 0x20211bb8 : user = 0x20211bbc
str() = 0x20211c58
dtor(.1.) : 0x20211c58
delete() : ** error - no deadbeef signpost @ 0x20211c58
dtor(.2.) : _pointer deleted
****************************************
//
// This test derives a class from ostrstream. It further overloads global
// "new"
// and "delete" such that the "new" allocates 4 bytes more then the requested
// amount of memory. The new uses the extra 4 bytes as a header at the
// beginning
// of the new'ed memory, puts 0xdeadbeef as a sign post in the 4 bytes, and
// returns a pointer to the user after the 4 byte sign post. The "delete"
// operator checks for sign post before free'ing the space. If the sign post
// does not exists, a message is printed out.
//
#include <stdio.h>
#include <stdlib.h>
#include <strstream.h>
// global new operator
void *operator new(size_t size);
// global delete operator
void operator delete(void *p);
class DiagOutput: public ostrstream
{
public:
char * _pointer;
public:
DiagOutput() : _pointer(0) {}
~DiagOutput();
char *safe_str();
};
DiagOutput::~DiagOutput()
{
if (_pointer) {
cout << "dtor(.1.) : " << (void*)_pointer << endl;
delete[] _pointer;
_pointer = 0;
cout << "dtor(.2.) : _pointer deleted" << endl;
}
}
// calls str() to return a pointer to the dynamically allocated
// str buffer
//
char *DiagOutput::safe_str()
{
if (!_pointer) {
_pointer = str();
cout << "str() = " << (void*)_pointer << endl;
}
return _pointer;
}
// overload global delete
//
void operator delete(void *p)
{
if (p) {
unsigned long *p1 = (unsigned long*)p;
p1--; // goto signpost
if (0xdeadbeef != *p1) {
cout << "delete() : ** error - no deadbeef signpost @ " << (void*) p << endl
;
}
else {
free(p1);
}
}
}
// overload global new
//
void* operator new(size_t size)
{
void *p = malloc(size+sizeof(unsigned long));
unsigned long *p1 = (unsigned long*)p; // get pointer to signpost
*p1 = 0xdeadbeef; // set the signpost
p1++; // set to start of user memory
cout << "new(" << size << ") : signpost = " << (void*)p
<< " : user = " << (void*)p1 << endl;
return((void*)p1);
}
main()
{
cout << "****************************************" << endl;
DiagOutput *log = new DiagOutput;
*log << "String1" << " String2" << endl << ends;
char *ss = log->safe_str();
delete log;
cout << "****************************************" << endl;
}
--
Freddie Mendoza
FVM Consulting International
Internet: avm@satori.com
avm@zilker.net
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Re: overloading global new and delete
Author: Fergus Henderson
Date: Sat, 14 Oct 1995 15:57
Date: Sat, 14 Oct 1995 15:57
63 lines
3296 bytes
3296 bytes
avm@zilker.net (Alfredo V. Mendoza) writes:
>The program below was a testcase sent to IBM compiler defect group.
>The problem is when compiled with IBM (413) xlC 3.1.2 , and ran
>the result is that the str() function in ostrstream does NOT use
>the overloaded new but uses the IBM runtime new. And when the class
>is destroyed the memory that was allocated by str() is deleted by the
>user defined global delete. Which (IMHO) is wrong.
The `ostrstream' class is not part of the draft C++ standard.
The old `char *' based strstream classes have been replaced by
a new set of `string' based stringstream classes.
So I'm afraid the draft C++ standard doesn't say anything about
about the behaviour of ostrstream::str().
Incidentally, the global operator new in your example was not
strictly conforming C++.
>// overload global new
>//
>void* operator new(size_t size)
>{
> void *p = malloc(size+sizeof(unsigned long));
>
> unsigned long *p1 = (unsigned long*)p; // get pointer to signpost
> *p1 = 0xdeadbeef; // set the signpost
> p1++; // set to start of user memory
> cout << "new(" << size << ") : signpost = " << (void*)p
> << " : user = " << (void*)p1 << endl;
> return((void*)p1);
>}
There is no guarantee that `p1' is suitably aligned here.
For example, this operator new will probably fail if you use it to
allocate a `double' on a SPARC, where doubles must be aligned
to 8-byte boundaries, but sizeof(long) == 4.
Another tricky issue is using `cout' in your global operator new.
Imagine what could happen if `ostream::operator<<' called your operator new:
your `::operator new' would call `ostream::operator<<', which could call
your `::operator new', which would call `ostream::operator<<', and so
on ... until stack overflow.
I think the current draft leaves it unspecified as to whether or not
library functions will call a user-defined global operator new.
>IBM compiler development claims that when one uses their runtime
>classes, it will always use the IBM runtime new and delete regardless
>of an overloaded global new and delete.
I imagine that one reason they do that is precisely to avoid the
problem of infinite recursion described above.
--
Fergus Henderson | "Australia is the richest country in the world,
fjh@cs.mu.oz.au | according to a new system of measuring wealth
http://www.cs.mu.oz.au/~fjh | announced by the World Bank yesterday."
PGP: finger fjh@128.250.37.3 | - Melbourne newspaper "The Age", 18 Sept 1995.
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Re: overloading global new and delete
Author: kanze
Date: Mon, 16 Oct 1995 15:04
Date: Mon, 16 Oct 1995 15:04
87 lines
4443 bytes
4443 bytes
In article <9528716.7351@mulga.cs.mu.OZ.AU> fjh@munta.cs.mu.OZ.AU
(Fergus Henderson) writes:
|> avm@zilker.net (Alfredo V. Mendoza) writes:
|> >The program below was a testcase sent to IBM compiler defect group.
|> >The problem is when compiled with IBM (413) xlC 3.1.2 , and ran
|> >the result is that the str() function in ostrstream does NOT use
|> >the overloaded new but uses the IBM runtime new. And when the class
|> >is destroyed the memory that was allocated by str() is deleted by the
|> >user defined global delete. Which (IMHO) is wrong.
|> The `ostrstream' class is not part of the draft C++ standard.
|> The old `char *' based strstream classes have been replaced by
|> a new set of `string' based stringstream classes.
|> So I'm afraid the draft C++ standard doesn't say anything about
|> about the behaviour of ostrstream::str().
See Steve Clamage's posting. (The exact text is in section D.3.1.2.)
|> Incidentally, the global operator new in your example was not
|> strictly conforming C++.
|> >// overload global new
|> >//
|> >void* operator new(size_t size)
|> >{
|> > void *p = malloc(size+sizeof(unsigned long));
|> >
|> > unsigned long *p1 = (unsigned long*)p; // get pointer to signpost
|> > *p1 = 0xdeadbeef; // set the signpost
|> > p1++; // set to start of user memory
|> > cout << "new(" << size << ") : signpost = " << (void*)p
|> > << " : user = " << (void*)p1 << endl;
|> > return((void*)p1);
|> >}
|> There is no guarantee that `p1' is suitably aligned here.
|> For example, this operator new will probably fail if you use it to
|> allocate a `double' on a SPARC, where doubles must be aligned
|> to 8-byte boundaries, but sizeof(long) == 4.
You (and the original poster) also are forgetting what happens when
malloc returns NULL.
Of course, under Unix, the above is fully conforming even when malloc
returns NULL, since aborting the program with an error message (in
this case, `segment violation') is a legal response when no memory is
available:-). (An interesting question: are user provided operator
new required to call the new_handler if no memory is present. I
presume not.)
|> Another tricky issue is using `cout' in your global operator new.
|> Imagine what could happen if `ostream::operator<<' called your operator new:
|> your `::operator new' would call `ostream::operator<<', which could call
|> your `::operator new', which would call `ostream::operator<<', and so
|> on ... until stack overflow.
|> I think the current draft leaves it unspecified as to whether or not
|> library functions will call a user-defined global operator new.
|> >IBM compiler development claims that when one uses their runtime
|> >classes, it will always use the IBM runtime new and delete regardless
|> >of an overloaded global new and delete.
|> I imagine that one reason they do that is precisely to avoid the
|> problem of infinite recursion described above.
Which still doesn't make it legal.
The traditional way of handling this in C and Unix was to use setbuf.
Strictly speaking, however, I don't think that it is guaranteed that
this will work; cout could still dynamically allocate memory for other
reasons. In practice, however, I suspect it will work.
--
James Kanze Tel.: (+33) 88 14 49 00 email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs-Bourgeois, F-67000 Strasbourg, France
Conseils en informatique industrielle --
-- Beratung in industrieller Datenverarbeitung
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Re: overloading global new and delete
Author: Thomas Maeder
Date: Thu, 19 Oct 1995 10:16
Date: Thu, 19 Oct 1995 10:16
22 lines
1520 bytes
1520 bytes
> From: fjh@munta.cs.mu.OZ.AU (Fergus Henderson) > Newsgroups: comp.std.c++ > Date: 14 Oct 1995 15:57:24 GMT > Organization: Computer Science, University of Melbourne, Australia > > avm@zilker.net (Alfredo V. Mendoza) writes: > > >IBM compiler development claims that when one uses their runtime > >classes, it will always use the IBM runtime new and delete regardless > >of an overloaded global new and delete. > > I imagine that one reason they do that is precisely to avoid the > problem of infinite recursion described above. Couldn't this problem be solved using a guard which prevents writing to cout in recursive calls of operator new()? Thomas --- [ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu. Contact address: std-c++-request@ncar.ucar.edu. The moderation policy is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Re: overloading global new and delete
Author: Fergus Henderson
Date: Sun, 22 Oct 1995 07:12
Date: Sun, 22 Oct 1995 07:12
31 lines
1953 bytes
1953 bytes
clamage@Eng.sun.com (Steve Clamage) writes: >The strstream functions must use the global operator >new and operator delete. Appendix D of the draft standard makes this clear. Ah yes, right you are. My earlier post stating that the standard didn't say anything about strstream was wrong. (Silly me, I didn't think that deprecated features would be in the Annex titled "Future Directions"! I guess I'll know to look harder next time ;-) One more point though: the example program overloaded only `operator new' and `operator delete'; it did not overload the array forms `operator new []' and `operator delete []'. Although the draft standard says that the default behaviour of `operator new [] (size_t size)' is just to call `operator new(size)', it does *not* say that the default behaviour of `operator delete[] (void *p)' is to call `operator delete (p)'. Instead it just says that it "reclaims [the] storage", without specifying how. [See 18.4.2.1.] From this I conclude that it is unspecified whether or not the replacement `operator delete' function in the example program would get called. -- Fergus Henderson WWW: http://www.cs.mu.oz.au/~fjh fjh@cs.mu.oz.au PGP: finger fjh@128.250.37.3 --- [ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu. Contact address: std-c++-request@ncar.ucar.edu. The moderation policy is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads