Topic: Am I missing something "new"?
Author: AllanW@my-dejanews.com
Date: 1998/08/04 Raw View
In article <35C631AA.309B@noSPAM.central.beasys.com>,
dtribble@technologist.com wrote:
> "Jorrit Tyberghein" <Jorrit.Tyberghein@uz.kuleuven.ac.be> wrote:
> >> Why is memcpy evil?
>
> AllanW@my-dejanews.com wrote:
> > [Opening bag of worms...]
> >
> > It isn't evil in specific cases, such as copying POD which is
> > guaranteed to contain no pointers.
>
> Not quite. Pod ("Plain Old Data") objects are classes with no
> constructors, destructors, virtual member functions, or non-public
> data members. In other words, PODs are essentially C structures.
> So they very well can contain pointers.
I didn't say that POD is always guaranteed to contain no pointers.
I said that if you're copying POD, and you can guarantee that it
contains no pointers, then it isn't evil.
[Notice the conspicuous lack of comma after "POD" in that sentance? No?
Look again, I'll wait... Hi again, did you look? There's no comma there
because I wasn't adding information about all POD. Instead, I was
qualifying. That means I was explaining which POD I referred to. Like in
the sentance
I didn't want to eat the steak which is cold
I didn't mean that all steak is cold, just the one I didn't want to eat.
Microsoft Word tells me that I should use the word "that" instead of the
word "which," but I routinely ignore Microsoft Word's advice.]
> The only problem with
> POD objects containing pointers is that copying the contents of
> the POD object means copying the contents of the pointers, which
> might not be what you intended.
It might be what you intended, if the data wasn't "owned." (For
instance, a key-sort might sort structures which point to records,
but since the records are on a linked list, the keys don't "own"
the records.) More commonly, it isn't what you intended, if the
pointer was supposed to be unique. Rather than open worm-bag#2
(gosh, it's slippery in here), I tried to sidestep the whole issue
by referring only to POD which is guaranteed to contain no pointers.
> But the reason that memcpy() works, and works quite well, on POD
> objects is that POD objects are very simple; they have very
> predictable arrangements and sizes, and they have no "hidden"
> members like _vtable pointers and such.
> Using memcpy() on anything more complicated than a POD object
> (which means non-POD objects), however, is dangerous.
We're saying the same thing, here.
[Shaking worms off of lower leg...]
-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Paul D. DeRocco" <pderocco@ix.netcom.com>
Date: 1998/08/05 Raw View
AllanW@my-dejanews.com wrote:
>
> I didn't say that POD is always guaranteed to contain no pointers.
> I said that if you're copying POD, and you can guarantee that it
> contains no pointers, then it isn't evil.
What matters isn't just whether the POD contains a pointer--copying a
pointer often works fine--but whether there exists somewhere else a
pointer back into the POD. Generally, the kinds of objects that can't be
memcpy-ed are those that are referred to directly by other object.
--
Ciao,
Paul
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: AllanW@my-dejanews.com
Date: 1998/08/05 Raw View
In article <35C7DE73.C91D522C@ix.netcom.com>,
"Paul D. DeRocco" <pderocco@ix.netcom.com> wrote:
> AllanW@my-dejanews.com wrote:
> >
> > I didn't say that POD is always guaranteed to contain no pointers.
> > I said that if you're copying POD, and you can guarantee that it
> > contains no pointers, then it isn't evil.
>
> What matters isn't just whether the POD contains a pointer--copying a
> pointer often works fine--but whether there exists somewhere else a
> pointer back into the POD. Generally, the kinds of objects that can't be
> memcpy-ed are those that are referred to directly by other object.
Presumably, code that is copying POD has a reason to do so.
It might be creating a new copy; even if it will be largely changed it
may start by copying an existing element to ensure it's completely
initialized. For instance, adding a new node to a linked list which is
NOT handled by an object. First, copy an existing node, then modify the
members, and finally link it into place.
Or, it might be moving POD to a new location, in which case the code
already knows how to update the pointers. If the data isn't pointed to
by some other object, why are you moving it to a new location?
Neither of these is the object-oriented way to do this; but if you're
using any of C++'s object-oriented tools, then memcpy() is evil after
all.
[Worms are now waist-high, and climbing...]
--
AllanW@my-dejanews.com is a "Spam Magnet" -- never read.
Please reply in USENET only, sorry.
-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: jcoffin@taeus.com (Jerry Coffin)
Date: 1998/08/04 Raw View
In article <35C631AA.309B@noSPAM.central.beasys.com>,
david.tribble@noSPAM.central.beasys.com says...
[ ... ]
> AllanW@my-dejanews.com wrote:
> > [Opening bag of worms...]
> >
> > It isn't evil in specific cases, such as copying POD which is
> > guaranteed to contain no pointers.
>
> Not quite. Pod ("Plain Old Data") objects are classes with no
> constructors, destructors, virtual member functions, or non-public
> data members. In other words, PODs are essentially C structures.
I think you're misinterpreting what he said -- he isn't saying "all
POD is guaranteed not to contain pointers." Rather, he's saying "It's
safe to copy something with memcpy if 1) it's POD, AND 2) it's
guaranteed not to contain any pointers."
--
Later,
Jerry.
The Universe is a figment of its own imagination.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: David R Tribble <david.tribble@noSPAM.central.beasys.com>
Date: 1998/08/01 Raw View
Dave wrote:
> It appears to me that the "new" operator in C++ always results in
> NON-RELOCATABLE block allocated in the heap...in other words it gives
> you a POINTER to a LOCKED block.
>
> Now, every personal operating system API, such as Macintosh and
> Windows, provides the ability to create HANDLES to RELOCATABLE blocks.
> ...
> In fact, Windows has been so anal about this, that the ONLY way to get
> a NON-relocatable Pointer to something, is that after you allocate the
> block, you must call HLOCK(), which returns the Pointer. (We all know
> this, right?)
Yeah, and we all know that all the world's a Vax...
> So...in standard C++...how in the world do you get a HANDLE to
> something using the "new" operator (without doing some big silly
> kluge, like writing your own routines in every program to overload the
> "new" operator...)
Firstly, the pointer returned by 'new', which refers to a memory block,
is isolated from the underlying O/S concept of memory blocks (or
"pages"). Allocating objects is only loosely related to allocating
virtual memory pages, and the thing that relates the two concepts
is the 'new' operator itself.
Secondly, you can't simply relocate objects in memory on whim.
What if the object contains pointers into itself (see the example
below)? Who does the fixing up in these cases? And what if I've
got other pointers (in other objects) pointing to the first object,
which has now been relocated in memory? Who fixes the pointers
in these cases?
Example:
class Foo
{
Foo();
char data[80]; // Some data
char * ptr; // A pointer
...
};
Foo::Foo():
ptr(&data[0]) // Init ptr to point to data[]
{
...
}
void func()
{
Foo * f;
f = new Foo;
f = relocate(f); // What happens to f->ptr here?
...
}
> I can't believe that the Founding Father(s) (and/or standards
> committee) of C++ overlooked the ability to obtain a HANDLE to a
> RELOCATABLE block, or require an overloaded "new" operator, since this
> ability is so fundamentally useful in every commercial operating
> system API...
Except Unix (POSIX), VMS, IBM OS/360, CTOS, PC-DOS, not to mention
all those thousands of embedded systems, ...
The C++ language standard is designed to cover as many operating
systems as possible, with the intention of allowing C++ compilers
to be written for them. This means that it can only assume a
simplistic, common set of capabilities that practically all operating
systems are capable of.
So the committee didn't overlook memory allocation handles any
more than they overlooked GUIs or digital signal processing. They
just didn't think that that sort of thing was universal enough to
include in a programming language standard.
-- David R. Tribble, dtribble@technologist.com --
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1998/08/01 Raw View
Dave wrote:
>
> Dear colleagues:
>
> If this is an obvious question, I will apologize in advance for being so
> dense. I have programmed in C for several years, and have been studying C++
> for the past several months...and am writing my first program with it.
> Everything is chugging along fine...But there is one question which baffles
> me. Am I missing something, or is there a big gap in the functionality of C++?
There is no big gap in the functionality of C++ - indeed there is much
*freedom* in C++ to make best uses of such things. For example, if
the implementor thinks that using relocatable blocks is a good idea,
he can decide to implement the *pointer* itself as HANDLE instead of
memory address. The C++ compiler then would do all the magic behind
the scenes, and the programmer wouldn't notice anything (except
that certain unportable things like getting the address by casting
a pointer to int and the likes won't work; however, those were never
guaranteed by the language, and can fail for different reasons as well,
the simplest being that sizeof(int) may be different from
sizeof(whatever*)).
>
> It appears to me that the "new" operator in C++ always results in
> NON-RELOCATABLE block allocated in the heap...in other words it gives you a
> POINTER to a LOCKED block.
If so, it's a choice of the implementation; maybe to improve
speed on pointer operations, maybe to maintain compatibility with
older versions which could not use that feature for some reason,
maybe just because of development cost considerations, or because
they just found that it *doesn't* give you a real net advantage,
possibly it's even just that they didn't think of this possibility
(it may be a combination of several reasons; maby it was too slow
when they considered it first, and now they have to stay compatible).
>
> Now, every personal operating system API, such as Macintosh and Windows,
> provides the ability to create HANDLES to RELOCATABLE blocks. This is so you
> don't fragment the heap like Swiss cheese...and the operating system's memory
> manager can compact the heap during housekeeping cycles.
Well, I think the ideal solution would be the OS to compact the
heap on *real* memory space *without* affecting the virtual addresses
the program uses at all. I can imagine some OSs working this way
(I don't however know much about the processor's virtual memory
handling, so it might just be impossible).
>
> In fact, Windows has been so anal about this, that the ONLY way to get a
> NON-relocatable Pointer to something, is that after you allocate the block,
> you must call HLOCK(), which returns the Pointer. (We all know this, right?)
No. Why do you assume we all program Windows?
>
> So...in standard C++...how in the world do you get a HANDLE to something using
> the "new" operator (without doing some big silly kluge, like writing your own
> routines in every program to overload the "new" operator...)
By using an implementationm which represents pointers as HANDLEs.
If there's no such implementation, blame the Vendors, not the standard.
It is allowed by the standard. Definitivly.
>
> I can't believe that the Founding Father(s) (and/or standards committee) of
> C++ overlooked the ability to obtain a HANDLE to a RELOCATABLE block, or
> require an overloaded "new" operator, since this ability is so fundamentally
> useful in every commercial operating system API...
Hmmm... I always thought there are lots of commercial Unixes out there,
but that must have been a misimpression... ;-)
>
> But I can't find mention of HANDLES in any C++ language reference...
Surely not - what would be a HANDLE in DOS?
(BTW, you could say you *do* find HANDLEs in C++ language reference:
they are called "pointer", and are usually implemented as memory
address.)
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: jcoffin@taeus.com (Jerry Coffin)
Date: 1998/08/01 Raw View
digidave@*NO**SPAM*xtramedia.com says...
> Now, every personal operating system API, such as Macintosh and Windows,
> provides the ability to create HANDLES to RELOCATABLE blocks. This is so you
> don't fragment the heap like Swiss cheese...and the operating system's memory
> manager can compact the heap during housekeeping cycles.
>
> In fact, Windows has been so anal about this, that the ONLY way to get a
> NON-relocatable Pointer to something, is that after you allocate the block,
> you must call HLOCK(), which returns the Pointer. (We all know this, right?)
This was only ever done to simulate an MMU on CPUs that didn't have
one in hardware. It became obsolete LONG ago in nearly every case.
Just for example, in Windows it was applicable in "real mode" only,
and the last version of Windows to support "real mode" was 3.0. In
"standard mode" or "386 mode" Windows 3.0 didn't need this anymore,
because it used the CPU's MMU to provide the level of indirection
without it being visible to user code.
I don't recall the intimate details of MacOS, but unless the design
was truly brain dead to start with (okay, I realize it was, but not
necessarily in this area) they should have been able to do away with
this nonsense around the time of the 68020 or so.
> I can't believe that the Founding Father(s) (and/or standards committee) of
> C++ overlooked the ability to obtain a HANDLE to a RELOCATABLE block, or
> require an overloaded "new" operator, since this ability is so fundamentally
> useful in every commercial operating system API...
I can't believe anybody is so thoroughly unaware of what's happened in
the last 7 or 8 years that they think this fundamental capability
would be of any use whatsoever anymore. I suppose some hand held
devices _might_ still use CPUs that lack MMUs, but I'm not even sure
they do. There are certain embedded microcontrollers that don't have
MMUs, but I can't imagine anybody trying to write a system on them
that would have a use for this sort of memory manager in software
either.
Don't let the UNIX heads mislead you about the nature of this
situation either: the ones who try to tell you the basic idea is
restricted to brain dead OSes or something like that simply don't know
much history. It's simply a matter of timing: if you look back far
enough, mainframes lacked this sort of hardware, and so when they got
sophisticated enough systems that they had a use for memory
management, but not the hardware to do it yet, they used the same
basic design. Later, the same basic thing happened in minicomputers,
and after that in microcomputers, and it's probably rippled down to
some of the hand-held devices now. The real difference isn't in the
sophistication level of Windows vs. UNIX, but in the timing of
introduction of MMUs on the machines they ran on.
In short, this was a short-term solution to shortcoming in hardware.
For most practical purposes, it's impossible to find such limited
hardware in a desktop machine anymore.
--
Later,
Jerry.
The Universe is a figment of its own imagination.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Paul D. DeRocco" <pderocco@ix.netcom.com>
Date: 1998/08/01 Raw View
Dave wrote:
>
> It appears to me that the "new" operator in C++ always results in
> NON-RELOCATABLE block allocated in the heap...in other words it gives
> you a POINTER to a LOCKED block.
>
> Now, every personal operating system API, such as Macintosh and
> Windows, provides the ability to create HANDLES to RELOCATABLE blocks.
> This is so you don't fragment the heap like Swiss cheese...and the
> operating system's memory manager can compact the heap during
> housekeeping cycles.
Even in a big flat-addressed OS like Win32, it is possible to fragment
memory to the point where it becomes useless. For instance:
void* prev;
void* curr = NULL;
while (true) {
prev = curr;
curr = malloc(256);
if (!curr) break;
if (prev) realloc(&prev, 1);
}
will eventually fill up the address space with alternating 1-byte
allocated chunks and nearly 256-byte free chunks. This problem isn't
solved in the least by having virtual memory, because all that does is
remap the address space on demand to a smaller physical memory, not
rearrange the virtual memory.
However, in practice, such a degree of fragmentation never occurs. In
real world applications, the amount of fragmentation merely adds some
overhead to the amount of memory required. Even if the amount of
overhead is as great as a hundred percent, it is easier just to
acknowledge that you have half as much memory as you thought (or buy
twice as much) than to solve the problem by introducing another layer of
indirection into every object reference. Such indirection slows things
down, and moving the objects around introduces other potential hard to
find, intermittent bugs.
Back when memory was hundred bucks a megabyte, and we were trying to run
Windows 3.1, this was an issue. Now that memory is well under a buck a
meg, it's no longer worth the trouble.
--
Ciao,
Paul
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: AllanW@my-dejanews.com
Date: 1998/08/02 Raw View
In article <901790726.31304@marvin>,
"Jorrit Tyberghein" <Jorrit.Tyberghein@uz.kuleuven.ac.be> wrote:
> idfix wrote in message <6podmh$44430@reader3.wxs.nl>...
> >Realloc has the same flaw as
> >
> > newptr = new X[y];
> > std::copy(...); /* no memcpy, it is evil when used on anything other
> >than a POD */
> > delete[] ptr;
> > ptr = newptr;
>
> Why is memcpy evil?
[Opening bag of worms...]
It isn't evil in specific cases, such as copying POD which is
guaranteed to contain no pointers. (But is anything in life ever
guaranteed?) In general, it's evil because some data cannot be
meaningfully copied this way. The classic example is data in a
struct or class, which may contain a pointer to single-instance
"contained" data. The "contained" data must be destroyed
exactly once, generally when the struct or class is destroyed.
The old BAD(tm) C way was to have every section of code that copies
the data with memcpy() also be aware of this special-case data, and
make approprite adjustments.
The new GOOD(tm) C++ way is to have the class be aware of it's own
data, implementing the copies in the copy constructor and the
assignment operator. Other code should be using C++ constructs,
which ensure that this code is called whenever appropriate.
> Just curious.
Okay, so you've probably not dealt with this phenomenon before.
In that case, my words may make sense, but you won't really get
it until you see some code. *sigh*
Here are some simple classes for the explanation below:
// A class of "contained" data.
class Foo {
int foo; // One int is enough for this example
public:
// Standard constructors, destrctors, and assignment
Foo(int f=0) : foo(f) {}
Foo(const Foo&f) : foo(f.foo) {}
const Foo&operator=(const Foo &f) { foo=f.foo; return *this; }
// Increment the embedded integer
const Foo&operator++() { ++foo; return *this; }
};
// A class which "contains" some data that must be
// destroyed exactly once.
class Bar {
Foo*f; // The contained data
public:
// The constructor allocates the "contained" data, and
// the destructor destroys it.
Bar(int i=0) : f(new Foo(i)) {}
~Bar() { delete Foo; }
// The copy constructor builds a new Bar from an old one.
// It can't copy the Foo* as-is, because each one needs
// to have it's own Foo object.
Bar(const Bar&b) : f(new Foo(b.f)) {}
// Assignment operator does something similar. In this case
// it can simply use Foo's assignment operator. In more
// elaborate circumstances, it might be neccesary to construct
// a new Foo object, then destroy the old one and fix the
// pointer.
const Bar&operator=(const Bar&b) { *f = *b.f; return *this; }
// Implement operator++ by incremeting the Foo.
const Bar&operator++() { ++f; return *this; }
// ...
};
The only thing unrealistic about these two classes is the fact
that the contained Foo really should be contained directly,
rather than through a pointer. But this isn't true in more
realistic cases, such as where Foo's constructor specifies
something that can't be changed without constructing a new
Foo. (A strained example might be a persistent class, where
the constructor specifies the filename and position to be
read and written.)
Now let's create a Bar object:
int main(int, char**) {
Bar bar1(5);
Now bar1 contains a Foo, which contains an integer foo=5. Assuming
the Bar is at address 100 and the Foo is at 104, we have:
+-100: Bar ---+ +-104: Foo ---+
| Foo*f = 104 | | int foo = 5 |
+-------------+ +-------------+
Now let's copy the Bar object:
{ // Create local scope
Bar bar2(bar1);
Assuming bar2 is at address 108, and the new Foo is at 112, we have:
+-100: Bar ---+ +-104: Foo ---+ +-108: Bar ---+ +-112: Foo ---+
| Foo*f = 104 | | int foo = 5 | | Foo*f = 112 | | int foo = 5 |
+-------------+ +-------------+ +-------------+ +-------------+
The Foo at 104 and the Foo at 112 look the same, so we'll change one:
++bar2;
Now we have
+-100: Bar ---+ +-104: Foo ---+ +-108: Bar ---+ +-112: Foo ---+
| Foo*f = 104 | | int foo = 5 | | Foo*f = 112 | | int foo = 6 |
+-------------+ +-------------+ +-------------+ +-------------+
Now let's copy bar2 on top of bar1. We have a copy constructor, but
we'll walk right around it by using memcpy() instead.
// *** POINT A ***
memcpy(&bar1, &bar2, sizeof(bar2));
Now we have
+-100: Bar ---+ +-104: Foo ---+ +-108: Bar ---+ +-112: Foo ---+
| Foo*f = 112 | | int foo = 5 | | Foo*f = 112 | | int foo = 6 |
+-------------+ +-------------+ +-------------+ +-------------+
Notice that the Foo at 104 still has value 5, but neither one of the
Bar's is pointing at it. Insted, they both point at the Foo at 112,
which has the value 6.
Now let's let Bar2 go out of scope.
} // End local scope
It's destructor is called, so the Foo at 112 is also destroyed. We have:
+-100: Bar ---+ +-104: Foo ---+ +-108: Unused-+ +-112: Unused-+
| Foo*f = 112 | | int foo = 5 | | | | |
+-------------+ +-------------+ +-------------+ +-------------+
Now bar1 is now pointing at unused data. When bar1 is deleted, it will
delete the Foo at 112 a second time, which is an error. Meanwhile, the
Foo at 104 will never be deleted, which is probably an error.
Let's fix this by going back to point A. Recall that relevant
memory looked like this:
+-100: Bar ---+ +-104: Foo ---+ +-108: Bar ---+ +-112: Foo ---+
| Foo*f = 104 | | int foo = 5 | | Foo*f = 112 | | int foo = 6 |
+-------------+ +-------------+ +-------------+ +-------------+
Well copy bar2 to bar1 again, but instead of using memcpy(),
we'll do it the C++ way, with the assignment operator:
bar1 = bar2;
This calls Bar::operator=, which correctly handles all of the
internal data. In this case, it simply calls foo's assignment
operator for the underlying data, so we end up with
+-100: Bar ---+ +-104: Foo ---+ +-108: Bar ---+ +-112: Foo ---+
| Foo*f = 104 | | int foo = 6 | | Foo*f = 112 | | int foo = 6 |
+-------------+ +-------------+ +-------------+ +-------------+
and everything is as it should be. The exact details of how to
handle the assignment are up to the code in Bar::operator=. It
could just as easily have decided to allocate a new Foo, initialize
it with the correct value, and then delete the old Foo. Whatever
works properly and efficiently.
I hope this helps.
[Try to close bag of worms... but bags of worms can't close...]
-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: 1998/08/02 Raw View
"Ross Smith" <ross.s@ihug.co.nz> writes:
>Dave wrote in message <6pm2l3$nku$1@supernews.com>...
>>
>>It appears to me that the "new" operator in C++ always results in
>>NON-RELOCATABLE block allocated in the heap...in other words it gives you a
>>POINTER to a LOCKED block.
>>
>>Now, every personal operating system API, such as Macintosh and Windows,
>>provides the ability to create HANDLES to RELOCATABLE blocks. This is so you
>>don't fragment the heap like Swiss cheese...and the operating system's memory
>>manager can compact the heap during housekeeping cycles.
>
>That technique is unusable with C++. C++ objects can't be relocated,
>because the operating system knows nothing about their internal
>structure; they might contain pointers or some other location-dependent
>information.
Saying that this technique is unusable with C++ is a bit of an
overstatement, IMHO. For an example of how it can be used in C++,
you need look no further than std::vector.
>The C++ designers didn't forget to put in an equivalent of realloc();
>they left it out on purpose, after very careful thought. If you need a
>reallocatable or relocatable array, you should be using the STL
>containers (vector etc).
So why couldn't `renew' use the same technique as std::vector?
The C++ designers may have thought about it carefully, but I still don't
agree with their conclusions -- I think a `renew' operation would
have been quite useful.
Something else that would be very helpful would be a template
std::move() operation whose default behaviour would be to call the
copy-constructor and then the destructor:
template <class T>
void std::move(T* old_location, void *new_location) {
new (new_location) T(*old_location);
old_location->~T();
}
The idea is that the behaviour of std::vector, renew, etc. could
be spcified in terms of std::move, and users could specialize
std::move for user-defined types to make things more efficient
(for example by avoiding the need to do a deep copy).
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: David R Tribble <david.tribble@noSPAM.central.beasys.com>
Date: 1998/08/04 Raw View
"Jorrit Tyberghein" <Jorrit.Tyberghein@uz.kuleuven.ac.be> wrote:
>> Why is memcpy evil?
AllanW@my-dejanews.com wrote:
> [Opening bag of worms...]
>
> It isn't evil in specific cases, such as copying POD which is
> guaranteed to contain no pointers.
Not quite. Pod ("Plain Old Data") objects are classes with no
constructors, destructors, virtual member functions, or non-public
data members. In other words, PODs are essentially C structures.
So they very well can contain pointers. The only problem with
POD objects containing pointers is that copying the contents of
the POD object means copying the contents of the pointers, which
might not be what you intended.
But the reason that memcpy() works, and works quite well, on POD
objects is that POD objects are very simple; they have very
predictable arrangements and sizes, and they have no "hidden"
members like _vtable pointers and such.
Using memcpy() on anything more complicated than a POD object
(which means non-POD objects), however, is dangerous.
-- David R. Tribble, dtribble@technologist.com --
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: swansond@netcom.com (Dennis Swanson)
Date: 1998/07/30 Raw View
Who would have guessed that on 29 Jul 98 11:46:31 GMT
Dave (digidave@*NO**SPAM*xtramedia.com) would say:
[...]
~ It appears to me that the "new" operator in C++ always results in
~ NON-RELOCATABLE block allocated in the heap...in other words it gives you a
~ POINTER to a LOCKED block.
It may appear that way, but it's not necessarily so.
~ Now, every personal operating system API, such as Macintosh and Windows,
~ provides the ability to create HANDLES to RELOCATABLE blocks. This is so you
~ don't fragment the heap like Swiss cheese...and the operating system's memory
~ manager can compact the heap during housekeeping cycles.
Is this still an issue with Macs? I had to futz around with MoreMasters()
and tables of toolbox calls that Apple promised wouldn't move memory when
I hacked Macs back in college in the mid- to late-80's, but that was
before System 7 and virtual memory. You need to worry about this on modern
Macs?
~ In fact, Windows has been so anal about this, that the ONLY way to get a
~ NON-relocatable Pointer to something, is that after you allocate the block,
~ you must call HLOCK(), which returns the Pointer. (We all know this, right?)
Actually, you must call GlobalLock() or LocalLock(), but this hasn't been
necessary since the days of Windows 3.0 and "real mode". Since Windows 3.1
("386 enhanced mode") all memory addresses are virtualized.
~ So...in standard C++...how in the world do you get a HANDLE to something using
~ the "new" operator (without doing some big silly kluge, like writing your own
~ routines in every program to overload the "new" operator...)
[...]
Hopefully your compiler vendor implemented the new operator in such a
way as not to cause problems on your system. The implementation of new
is machine-dependent and outside the scope of the standard.
Den
--
Dennis M. Swanson <>< C/Win32 API programmer UNIX hobbyist
Is that what you'd call it?
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "BURL" <NOSPAM@NOSPAM.NOSPAM>
Date: 1998/07/30 Raw View
Dave wrote in message <6pm2l3$nku$1@supernews.com>...
>I can't believe that the Founding Father(s) (and/or standards committee) of
>C++ overlooked the ability to obtain a HANDLE to a RELOCATABLE block, or
>require an overloaded "new" operator, since this ability is so
fundamentally
>useful in every commercial operating system API...
>
>But I can't find mention of HANDLES in any C++ language reference...
This *could* be b/c HANDLE's are OS-dependent...
My advice:
Create a single, *reusable* library (e.g., RESIZE.LIB) which overloads new
and delete and adds a third function [e.g., ResizeBuffer(PVOID&,ULONG) ] for
resizing the buffer. I don't know about MAC, but under Windozer, you can
map an allocated pointer back to its underlying HANDLE, (Check the API if
you don't believe me...) and then ask the OS to reposition it. If the MAC
doesn't support it, you could probably add that functionality anyway ( have
a VOID* to HANDLE map ).
*A word of warning, though:*
As with realloc in the C rtl, if you have multiple pointers to the same
address, then all of them (except the one you're moving) will break. This
is standard fare when dealing with pointers, so if you can't figure out how
to handle it, then you're a FRICKIN' MORON!
BTW,
One respondant answered with comments mentioning the fact that various RTL's
will minimize handle usage. This is irrelevant to the original poster's
question. He *WANTS* to use HANDLE's.
Furthermore, he *WANTS* to be able to reposition the buffer in memory with
the OS handling the memory movement for him. I believe that doing a
GlobalRealloc under Windows (95/NT) does not incur a memory copy when the
buffer has to be moved; I'm pretty sure that Windows merely updates the page
table so that your old pages reside at new virtual addresses. This, of
course, means that the "evil" memcpy is, in fact, avoided. Mac probably
doesn't support this, either, but it's a nice perf boost.
Also, realloc does not necessarily cause memory to be moved. In fact,
contrary to Silvio Bierman's assertions, it *rarely* does. This is why code
like the following usually works in spite of the obvious bug (it typically
breaks under heavy memory load):
{
char* sz=malloc(32);
char* szr = sz;
sz=realloc(sz,64);
memset(szr,0,64);
// BUGBUG: szr is not gauranteed to be correct,
// b/c realloc may have moved the buffer
// that it pointed to!
free(szr);
}
--BURL
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Christof Stadler <c.stadler@delta-ii.de>
Date: 1998/07/30 Raw View
Dave,
Dave wrote:
> In fact, Windows has been so anal about this, that the ONLY way to get a
> NON-relocatable Pointer to something, is that after you allocate the block,
> you must call HLOCK(), which returns the Pointer. (We all know this, right?)
This was true up to Windows 3.1 or so. Even in the latest Win16
versions, the relocation of memory is handled with the help of the MMU
(i.e. the physical address of the memory does not change when it is
relocated). But in the old days, this was really a problem: Allocating
memory via "new" caused the memory to be not relocateable.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sbnaran@fermi.ceg.uiuc.edu (Siemel Naran)
Date: 1998/07/30 Raw View
>> std::copy(...); /* no memcpy, it is evil when used on anything other
>Why is memcpy evil?
>Just curious.
Not really a std++ question.
Because operator= may have been overloaded for your class. For example, if
a class manages dynamic memory, the class itself contains a pointer. So a
bitwise copy would copy pointers! It would not copy the actual data pointed
to. Only the overloaded operator= will do this. Your class might even do
reference counting. It might not even have an operator=, or the operator=
is protected. Then std::copy will give you an error. But no so with
memcpy.
Anyway, since std::copy is a template, then when it is expanded out for ints,
it should reduce to a memcpy (with an advanced optimizer, of course).
--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "John Burton" <jb@mail.com>
Date: 1998/07/30 Raw View
Tried to email this first but your email address wasn't valid...
Modern operating systems all reply on the ability of the CPU
to map physical memory blocks into any virtual address location
they want. It doesn't matter how fragmented physical memory gets
because the operating system can gather up any spare pages of
memory and map them into a continuous block as far as application
programs are concerned.
Most operating systems have at least 2G of user addressable
memory space so even if some of this does become
fragmented it's not a big program for most application
programs.
Dave wrote in message <6pm2l3$nku$1@supernews.com>...
>Dear colleagues:
>
>If this is an obvious question, I will apologize in advance for being so
>dense. I have programmed in C for several years, and have been studying C++
>for the past several months...and am writing my first program with it.
>Everything is chugging along fine...But there is one question which baffles
>me. Am I missing something, or is there a big gap in the functionality of
C++?
>
>It appears to me that the "new" operator in C++ always results in
>NON-RELOCATABLE block allocated in the heap...in other words it gives you a
>POINTER to a LOCKED block.
>
>Now, every personal operating system API, such as Macintosh and Windows,
>provides the ability to create HANDLES to RELOCATABLE blocks. This is so
you
>don't fragment the heap like Swiss cheese...and the operating system's
memory
>manager can compact the heap during housekeeping cycles.
>
>In fact, Windows has been so anal about this, that the ONLY way to get a
>NON-relocatable Pointer to something, is that after you allocate the block,
>you must call HLOCK(), which returns the Pointer. (We all know this,
right?)
>
>So...in standard C++...how in the world do you get a HANDLE to something
using
>the "new" operator (without doing some big silly kluge, like writing your
own
>routines in every program to overload the "new" operator...)
>
>I can't believe that the Founding Father(s) (and/or standards committee) of
>C++ overlooked the ability to obtain a HANDLE to a RELOCATABLE block, or
>require an overloaded "new" operator, since this ability is so
fundamentally
>useful in every commercial operating system API...
>
>But I can't find mention of HANDLES in any C++ language reference...
>
>Thanks for any explanations...
>
>--Dave
>
>To send, EMail, remove '*NO**SPAM*' from the Return Address. Thank you...
>---
>[ comp.std.c++ is moderated. To submit articles, try just posting with ]
>[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
>[ --- Please see the FAQ before posting. --- ]
>[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: tom_lippincott@advisories.com (Tom Lippincott)
Date: 1998/07/30 Raw View
digidave@*NO**SPAM*xtramedia.com wrote:
> I can't believe that the Founding Father(s) (and/or standards committee) of
> C++ overlooked the ability to obtain a HANDLE to a RELOCATABLE block, or
> require an overloaded "new" operator, since this ability is so fundamentally
> useful in every commercial operating system API...
I'm afraid they did. And, speaking as a mac-head myself, I'm glad they
did. Handles are one of those things which seemed like a good idea at the
time,
but which are now more of a nuisance.
(What was really needed was a programming style which allowed
encapsulation below the level of a heap block; C++ has been a big help for
me there.)
That said, the best way I've found to deal with handles is to write a class
to represent the master pointer. (In case Windows has a different lexicon:
a handle points to a master pointer, which points to the thing that can move.)
A master pointer has special new and delete operators, which call the
operating system routines for allocating handles.
--Tom Lippincott
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Valentin Bonnard <bonnardv@pratique.fr>
Date: 1998/07/30 Raw View
Dave <digidave@*NO**SPAM*xtramedia.com> writes:
> If this is an obvious question, I will apologize in advance for being so
> dense. I have programmed in C for several years, and have been studying C++
> for the past several months...and am writing my first program with it.
> Everything is chugging along fine...But there is one question which baffles
> me. Am I missing something, or is there a big gap in the functionality of C++?
None
> It appears to me that the "new" operator in C++ always results in
> NON-RELOCATABLE block allocated in the heap...in other words it gives you a
> POINTER to a LOCKED block.
Correct. So you can safely use its return value: the memory won't
move randomly.
> Now, every personal operating system API, such as Macintosh and Windows,
> provides the ability to create HANDLES to RELOCATABLE blocks.
On a real OS, one doesn't need handles. Only broken
OSes have this bug called 'handle'.
> In fact, Windows has been so anal about this, that the ONLY way to get a
> NON-relocatable Pointer to something, is that after you allocate the block,
> you must call HLOCK(), which returns the Pointer. (We all know this, right?)
No, I know that, some other people know that, but we don't _all_
know that.
> So...in standard C++...how in the world do you get a HANDLE to something using
> the "new" operator (without doing some big silly kluge, like writing your own
> routines in every program to overload the "new" operator...)
You don't.
> I can't believe that the Founding Father(s) (and/or standards committee) of
> C++ overlooked the ability to obtain a HANDLE to a RELOCATABLE block, or
That wasn't overlooked.
> require an overloaded "new" operator, since this ability is so fundamentally
> useful in every commercial operating system API...
It is not fundamental nor useful on a correctly designed OS.
> But I can't find mention of HANDLES in any C++ language reference...
On the Macintosh, handles are mostly usefull for blocks you really
want to resize (for MacOS fans: WindowPtr vs TEHandle). You can use
malloc/realloc/free provide the resize abstraction; a
good implementation could do something like that:
void* malloc_big_block (size_t s)
{
Handle h = NewHandle (s); // allocates suitably aligned memory
// of size s or returns NULL; the value returned is a char**
// the value of *h can vary at many points in the program
if (h)
{
HLock (h); // *h can't change anymore
register_handle (h); // so we can find it latter
return *h;
}
else
return NULL;
}
void* realloc_big_block (void* p, size_t s)
{
if (p == NULL)
return malloc_big_block (p);
Handle h = find_handle (p);
HUnlock (h); // *h will probably now change
SetHandleSize (h, s); // the bitwise content of the block
// will be preserved
HLock (h);
return *h;
}
void free (void* p)
{
Handle h = find_handle (p);
ReleaseHandle (h);
}
Note: Handles here shouldn't be confused with the handle pattern.
If you want to use MacOS' handles, C++ makes it bit safer and
easier than C with ressource aquisition is innitialisation
(smart pointers).
--
Valentin Bonnard mailto:bonnardv@pratique.fr
info about C++/a propos du C++: http://pages.pratique.fr/~bonnardv/
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Edward Diener <eddielee@abraxis.com>
Date: 1998/07/30 Raw View
I have never seen anything in the C++ standard or in any of the books I
have read on the standard ( Stroustrup 3rd edition or Lippman 3rd
edition ) that says anything about whether the new operator allocates a
relocatable or non-relocatable block. I do not believe that this is
part of the standard since it is very hardware and operating system
dependent. If it is in the standard somewhere, please quote the
passage.
In Windows programming you are a little behind the times. Locking
memory is no longer an issue in 32 bit Windows programming since memory
is virtual and a virtual address can refer to nearly any place in
actual memory and the place to which it refers can be moved around
without affecting the pointer to the virtual memory that you have.
Furthermore nearly every compiler implementation in Windows allocates
large size blocks from the operating system and then dispenses memory
from those blocks in an attempt at faster speed and to avoid the
particular fragmentation problems that you are worried about.
Finally in WIN32 programming you can go straight to the operating and
allocate memory if you want to control the process more ( VirtualAlloc
does this ) . Then, if you like, you can use the C++ 'new' placement
syntax to allocate your C++ memory from the block that you have gotten
from the operating system if you like.
Dave wrote:
> Dear colleagues:
>
> If this is an obvious question, I will apologize in advance for being so
> dense. I have programmed in C for several years, and have been studying C++
> for the past several months...and am writing my first program with it.
> Everything is chugging along fine...But there is one question which baffles
> me. Am I missing something, or is there a big gap in the functionality of C++?
>
> It appears to me that the "new" operator in C++ always results in
> NON-RELOCATABLE block allocated in the heap...in other words it gives you a
> POINTER to a LOCKED block.
>
> Now, every personal operating system API, such as Macintosh and Windows,
> provides the ability to create HANDLES to RELOCATABLE blocks. This is so you
> don't fragment the heap like Swiss cheese...and the operating system's memory
> manager can compact the heap during housekeeping cycles.
>
> In fact, Windows has been so anal about this, that the ONLY way to get a
> NON-relocatable Pointer to something, is that after you allocate the block,
> you must call HLOCK(), which returns the Pointer. (We all know this, right?)
>
> So...in standard C++...how in the world do you get a HANDLE to something using
> the "new" operator (without doing some big silly kluge, like writing your own
> routines in every program to overload the "new" operator...)
>
> I can't believe that the Founding Father(s) (and/or standards committee) of
> C++ overlooked the ability to obtain a HANDLE to a RELOCATABLE block, or
> require an overloaded "new" operator, since this ability is so fundamentally
> useful in every commercial operating system API...
>
> But I can't find mention of HANDLES in any C++ language reference...
>
> Thanks for any explanations...
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "idfix" <idfix@wxs.nl>
Date: 1998/07/30 Raw View
Realloc has the same flaw as
newptr = new X[y];
std::copy(...); /* no memcpy, it is evil when used on anything other
than a POD */
delete[] ptr;
ptr = newptr;
which is that the pointer returned by realloc may (and in most practical
cases will) be different from the pointer that went in. In that case,
realloc will do exactly the same (and will use memcpy)
Silvio Bierman
Jorrit Tyberghein wrote in message <901722541.675513@marvin>...
>Robert Youdan wrote in message <35bf2228.0@nexus.comcen.com.au>...
>>Your compiler will have implemented their run-time libraries to do all this
>>work for you. Borland's, for example, requests larger chunks of memory from
>>windows and subdivides that for your allocation needs to reduce the number
>>of windows handles needed. I am sure all good RTLs do similar things.
>>
>>Rob
>
>But the question was (I think): what if you want to reallocate the memory.
>i.e. make the memory block larger without having to do new/memcpy/delete.
>
>In C you have malloc, free AND realloc.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Robert Youdan" <rob@event-horizonsXXNOSPAMXX.com.au>
Date: 1998/07/30 Raw View
No, he was asking about "re-locatable" memory, not "re-allocatable".
Relocatable memory is sub-system dependent. See a later posting for a good
explanation.
Cheers,
Rob
--
Please remove "XXSPAMXX" before replying by e-mail
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Martijn Lievaart" <nobody@orion.nl>
Date: 1998/07/30 Raw View
Dave wrote in message <6pm2l3$nku$1@supernews.com>...
>Dear colleagues:
>
>If this is an obvious question, I will apologize in advance for being so
>dense. I have programmed in C for several years, and have been studying C++
>for the past several months...and am writing my first program with it.
>Everything is chugging along fine...But there is one question which baffles
>me. Am I missing something, or is there a big gap in the functionality of
C++?
>
>It appears to me that the "new" operator in C++ always results in
>NON-RELOCATABLE block allocated in the heap...in other words it gives you a
>POINTER to a LOCKED block.
The whole concept of locked blocks is a Mac/Windows 2.x concept, although I
doubt if Mac/M$ came up with it themselves.
>
>Now, every personal operating system API, such as Macintosh and Windows,
>provides the ability to create HANDLES to RELOCATABLE blocks. This is so
you
>don't fragment the heap like Swiss cheese...and the operating system's
memory
>manager can compact the heap during housekeeping cycles.
Not true. This was important only for OSses that had very little memory to
play with.
>
>In fact, Windows has been so anal about this, that the ONLY way to get a
>NON-relocatable Pointer to something, is that after you allocate the block,
>you must call HLOCK(), which returns the Pointer. (We all know this,
right?)
>
Why would you want a pointer to a locked block under Windows? Let the mmu
take care of memory stuff, you get a pointer, you use it. No hassle. What
you are referring to is the memorymanagement mess under Windows 3.0/3.1
where people were allocating locked blocks to avoid the memory from moving
around. But because the mmu takes care of this under Windows 3 and up, this
was not importand anymore and Windows just turned of the NONMOVEABLE bit
except under some extreem circumstances where it may have mattered.
>So...in standard C++...how in the world do you get a HANDLE to something
using
>the "new" operator (without doing some big silly kluge, like writing your
own
>routines in every program to overload the "new" operator...)
>
If you mean, how do you re-alloc a block allocated with new? You don't.
There are other solutions like using the STL. Still this is one of those
areas were C++ is actually a little harder to use than C. There are good
reasons for this. However, when using POD's without holding on to pointers
to this POD, nothing prevents you from using malloc/realloc/free like C.
>I can't believe that the Founding Father(s) (and/or standards committee) of
>C++ overlooked the ability to obtain a HANDLE to a RELOCATABLE block, or
>require an overloaded "new" operator, since this ability is so
fundamentally
>useful in every commercial operating system API...
>
Nope, only in some <flame>retarded</flame> OSses that luckily are moving to
more mature memory management nowadays.
>But I can't find mention of HANDLES in any C++ language reference...
>
Hope I explained why.
Greetz,
Martijn (see sig for email address)
--
#include <stddisclaimer.h>
My email address is intentionally invalid agains spam.
Please reply to mlievaar at orion in nl
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Ross Smith" <ross.s@ihug.co.nz>
Date: 1998/07/30 Raw View
Dave wrote in message <6pm2l3$nku$1@supernews.com>...
>
>It appears to me that the "new" operator in C++ always results in
>NON-RELOCATABLE block allocated in the heap...in other words it gives you a
>POINTER to a LOCKED block.
>
>Now, every personal operating system API, such as Macintosh and Windows,
>provides the ability to create HANDLES to RELOCATABLE blocks. This is so you
>don't fragment the heap like Swiss cheese...and the operating system's memory
>manager can compact the heap during housekeeping cycles.
That technique is unusable with C++. C++ objects can't be relocated,
because the operating system knows nothing about their internal
structure; they might contain pointers or some other location-dependent
information. This is why the automatically generated copy constructor
and assignment operator use recursive calls to the members' copy
operations, instead of a simple bitwise copy as C would do with a
struct. And you still have to write your own copy operations for
nontrivial classes. For that matter, some classes *can't* be copied.
The C++ designers didn't forget to put in an equivalent of realloc();
they left it out on purpose, after very careful thought. If you need a
reallocatable or relocatable array, you should be using the STL
containers (vector etc).
This is all covered in the C++ FAQ.
--
Ross Smith ................................... mailto:ross.s@ihug.co.nz
.............. The Internet Group, Auckland, New Zealand ..............
"Remember when we told you there was no future? Well, this is it."
-- Blank Reg
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: AllanW@my-dejanews.com
Date: 1998/07/30 Raw View
In article <6pm2l3$nku$1@supernews.com>,
digidave@*NO**SPAM*xtramedia.com wrote:
> Dear colleagues:
>
> If this is an obvious question, I will apologize in advance for being so
> dense. I have programmed in C for several years, and have been studying C++
> for the past several months...and am writing my first program with it.
> Everything is chugging along fine...But there is one question which baffles
> me. Am I missing something, or is there a big gap in the functionality of
> C++?
You are missing something.
> It appears to me that the "new" operator in C++ always results in
> NON-RELOCATABLE block allocated in the heap...in other words it gives you a
> POINTER to a LOCKED block.
You could say that. It is analagous to the malloc() function in C,
except that certain important side-effects also occur (such as
calling the object's constructor, if it has one).
> Now, every personal operating system API, such as Macintosh and Windows,
> provides the ability to create HANDLES to RELOCATABLE blocks. This is so you
> don't fragment the heap like Swiss cheese...and the operating system's memory
> manager can compact the heap during housekeeping cycles.
>
> In fact, Windows has been so anal about this, that the ONLY way to get a
> NON-relocatable Pointer to something, is that after you allocate the block,
> you must call HLOCK(), which returns the Pointer. (We all know this, right?)
No, not everybody here knows that. This is an OS-dependant issue,
something which C++ and other languages are designed to hide. Those
who never had to do it may know nothing about it. And today, even
Windows isn't so anal about it.
In *ANY* C++ system, operator new is required to find some memory and
make it available for use. Realistically, it must also return the
memory to the OS when the program terminates. But how it goes about
this is entirely up to the compiler designer.
> So...in standard C++...how in the world do you get a HANDLE to something
> using the "new" operator (without doing some big silly kluge, like writing
> your own routines in every program to overload the "new" operator...)
>
> I can't believe that the Founding Father(s) (and/or standards committee) of
> C++ overlooked the ability to obtain a HANDLE to a RELOCATABLE block, or
> require an overloaded "new" operator, since this ability is so fundamentally
> useful in every commercial operating system API...
>
> But I can't find mention of HANDLES in any C++ language reference...
General rule of thumb: you never get a handle to anything provided by
the C++ compiler or the C++ library. There is often a need to get a
handle to something provided by a third-party library, which in this
case includes the Windows API.
Let's step back from the problem for a moment.
It sounds to me as if your experience was with Windows 3.0 or
earlier. Short history lesson: These 16-bit systems worked with
memory "segments" of up to 64Kbytes at a time. "Cooperative
multitasking" meant that multitasking was partially implemented
in the program, rather than in the OS -- a program was required
to call "GetMessage" from time to time, even if it knew that
there were no messages pending, in order to allow the operating
system to let other programs run if needed. The Virtual Memory
mechanism was also implemented manually; programs were required
to "unlock" memory until needed and then "lock" them before any
access. In programs designed to work in "real mode" (the only
mode that would work on old or low-end PCs), each "lock" of a
RELOCATABLE resource (almost all of them) could return a
different memory address -- making such things as linked lists
very difficult to implement. The only solution was to save the
handle returned when the memory was allocated. The programmer
used the handle to lock memory, access the object, and then unlock
the memory again.
(Looking back, it's amazing we were able to accomplish anything
at all!)
When Windows 3.1 came out, it abandoned "real mode". The concept
of RELOCATABLE was practically obsolete; almost all resources
(except memory in device drivers and other interrupt handlers)
were RELOCATABLE, but since the call to "lock" would always return
the same address, it was nevertheless safe to keep an address to a
memory element.
When Windows 3.11 came out, they also abandoned the "standard mode,"
leaving only "enhanced mode." Now the calls to lock() and unlock()
became null operations; again, almost every byte in memory was
subject to swapping out automatically, but since it would be swapped
back in transparently at the exact same address, the locking was no
longer needed.
At around this same time, someone in charge finally realized that
the whole concept behind the Windows API function MakeProcInstance
was there to mask an OS issue that the compiler could have solved
transparently. New compilers came out in which the use of this
function was completely optional.
When Windows 95 came out, they finally abandoned the "cooperative
multitasking" completely, and even implemented "multithreaded"
programs (which act similar to two or more tasks working together).
Thus, it's not even required that a program call GetMessage in a
timely manner anymore (although there are still some reasons to
want to do this).
In short, make a list of all the things that you COULD have done,
but you knew that you never SHOULD do, because then the entire
operating system would slow to a crawl or even stop. Now cross
off everything that involved the Windows API -- it isn't required
anymore. (You still need to make your program as efficient as
possible, of course, but that's not a Windows issue.)
That's not to say that the concept of HANDLES has completely gone
away. For instance, if you want to draw a line on a window, you need
HANDLEs to the window you will draw in and the pen you will use to
draw it. (Most C++ compilers for Windows 95 come with "Microsoft
Foundation Classes, which include classes to manipulate these handles
more automatically -- but the handles still exist at a low level.)
This is not unique to Windows programming. If you use almost any
third-party tool that allows you to accomplish two things at the same
time (like two Windows in Microsoft Windows), the API will specify a
HANDLE so that each function call can specify which "thing" to affect.
Sometimes these go by other names -- one common name is "magic
cookie," but it's exactly the same concept. For instance, an API to
play a MIDI keyboard would probably require a handle to specify which
MIDI device and/or "voice" to play.)
In C++ programs on Microsoft Windows, you can rest assured that
operator new() does almost everything you will need to do without
you having to specify any details about how to do it. If you have
enough physical memory and/or disk space, you can allocate as much
as 2048 Megabytes of data without worrying if your "Heap" is
becoming "Swiss Cheese."
However, there are a (very!) few remaining cases where you still
need an actual handle to memory allocated directly by Windows,
without going through operator new() first. In this case, you
can still call functions with the same name that you used in
Windows 3.0 -- for instance, you can call GlobalAlloc() or
LocalAlloc(). You won't find this in any documentation on C++,
so check out a book on the Windows API instead.
Note: Since these are Windows questions, and not C++ standards
issues, follow-ups should go to group comp.os.ms-windows .
-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Jorrit Tyberghein" <Jorrit.Tyberghein@uz.kuleuven.ac.be>
Date: 1998/07/30 Raw View
idfix wrote in message <6podmh$44430@reader3.wxs.nl>...
>Realloc has the same flaw as
>
> newptr = new X[y];
> std::copy(...); /* no memcpy, it is evil when used on anything other
>than a POD */
> delete[] ptr;
> ptr = newptr;
Why is memcpy evil?
Just curious.
Greetings,
--
---------------------------------------------------------------------------
Jorrit Tyberghein (Jorrit.Tyberghein@uz.kuleuven.ac.be)
Project Manager of Crystal Space, a free and portable 3D 6DOF portal engine.
More info at: http://www.geocities.com/SiliconValley/Horizon/3856/
---------------------------------------------------------------------------
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Dave <digidave@*NO**SPAM*xtramedia.com>
Date: 1998/07/29 Raw View
Dear colleagues:
If this is an obvious question, I will apologize in advance for being so
dense. I have programmed in C for several years, and have been studying C++
for the past several months...and am writing my first program with it.
Everything is chugging along fine...But there is one question which baffles
me. Am I missing something, or is there a big gap in the functionality of C++?
It appears to me that the "new" operator in C++ always results in
NON-RELOCATABLE block allocated in the heap...in other words it gives you a
POINTER to a LOCKED block.
Now, every personal operating system API, such as Macintosh and Windows,
provides the ability to create HANDLES to RELOCATABLE blocks. This is so you
don't fragment the heap like Swiss cheese...and the operating system's memory
manager can compact the heap during housekeeping cycles.
In fact, Windows has been so anal about this, that the ONLY way to get a
NON-relocatable Pointer to something, is that after you allocate the block,
you must call HLOCK(), which returns the Pointer. (We all know this, right?)
So...in standard C++...how in the world do you get a HANDLE to something using
the "new" operator (without doing some big silly kluge, like writing your own
routines in every program to overload the "new" operator...)
I can't believe that the Founding Father(s) (and/or standards committee) of
C++ overlooked the ability to obtain a HANDLE to a RELOCATABLE block, or
require an overloaded "new" operator, since this ability is so fundamentally
useful in every commercial operating system API...
But I can't find mention of HANDLES in any C++ language reference...
Thanks for any explanations...
--Dave
To send, EMail, remove '*NO**SPAM*' from the Return Address. Thank you...
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Robert Youdan" <rob@event-horizonsXXNOSPAMXX.com.au>
Date: 1998/07/29 Raw View
Your compiler will have implemented their run-time libraries to do all this
work for you. Borland's, for example, requests larger chunks of memory from
windows and subdivides that for your allocation needs to reduce the number
of windows handles needed. I am sure all good RTLs do similar things.
Rob
--
Please remove "XXSPAMXX" before replying by e-mail
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Jorrit Tyberghein" <Jorrit.Tyberghein@uz.kuleuven.ac.be>
Date: 1998/07/29 Raw View
Robert Youdan wrote in message <35bf2228.0@nexus.comcen.com.au>...
>Your compiler will have implemented their run-time libraries to do all this
>work for you. Borland's, for example, requests larger chunks of memory from
>windows and subdivides that for your allocation needs to reduce the number
>of windows handles needed. I am sure all good RTLs do similar things.
>
>Rob
But the question was (I think): what if you want to reallocate the memory.
i.e. make the memory block larger without having to do new/memcpy/delete.
In C you have malloc, free AND realloc.
Greetings,
--
---------------------------------------------------------------------------
Jorrit Tyberghein (Jorrit.Tyberghein@uz.kuleuven.ac.be)
Project Manager of Crystal Space, a free and portable 3D 6DOF portal engine.
More info at: http://www.geocities.com/SiliconValley/Horizon/3856/
---------------------------------------------------------------------------
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Jeff Elliott <cguru@zebra.net>
Date: 1998/07/29 Raw View
Hi Dave,
My gut reaction to your post is that you're probably dabbling in areas
which are decidedly beyond the scope of any language standards. Rather,
allocating memory in a relocatable fashion seems to me to be rather an
OS-dependent feature. In the same sense that C++ as a "programming
language" doesn't (and can't) dictate how to work with drawing graphics on
a video output device, I/O in general, and other hardware-specific
features such as serial ports, parallel ports, network adapters, ISDN
adapters, mice, printers, USB ports, ACPI or other power management
hardware... it seems to me that the concept of allocating and managing
memory is well beyond the scope of any language standards and well into
the specifics of how a particular operating system implements such
features.
Remember, when you "new" or malloc() some memory, these C/C++ functions
simply request such services from the underlying operating system. How
that OS chooses to handle these requests is up to the OS itself -- that
kind of detail can't be written into the programming languages since they
run on so many different types of machines.
In DOS, for example, there was no concept of "handles" to allocated memory
blocks. In Unix, AFAIK the same holds true. For all the hundreds
(thousands?) of other operating systems for which a C and/or C++ compiler
exists, well, I can't talk about all those.
I think you might be looking for a Windows API-specific or
Microsoft-specific answer to your dilemma. While there's no way any kinds
of standards committee (which deals with ALL makes and models of compiler
software and hardware architecture) could possibly hope to impose that
kind of low-level control over all the OS makers, compiler makers, and
hardware makers out there, surely Microsoft has implemented such
functionality on their own -- in order to deal with a known OS and the
relatively small smattering of hardware which supports their OS.
Have you checked your MSVC++ online help system for entries along these
lines? I think I could just about guarantee you won't find such answers
in a generic book on C or C++ programming, but there's a chance Microsoft
has added such a "Microsoft-specific extension" to their development
environment.
Also keep in mind that if you DO find a solution which works under
MS-Windows, it more than likely won't work on any other development
platform. Such is the way of proprietary extensions to a programming
language which are targeted at a specific OS or hardware platform.
FWIW, the whole concept of a "HANDLE", including the keyword itself, is
not a part of either the C or C++ programming language at all. Other
compilers may support it as well, and I don't know who "invented" it
first, but a "HANDLE" is just a typedef'd data type created in WTYPES.H
for MSVC++ 5.0 (line 151 of that file). This file name is short for
"Windows Data Types", and is not, as you can probably already tell, NOT
part of any language standard.
This is how Microsoft chose to do it, which is fine -- as long as you're
using Microsoft compilers to write code for a Microsoft operating system
that you don't care to port to any other OS or hardware platform. Sure,
there's certainly a lot of that type of machine out there, but Microsoft
surely can't claim to "own" the entire C++ programming language! Although
some of their proprietary extensions which take useful advantage of some
of the peculiarities of their own operating systems can become kind of
"second nature" to the programmer who never ventures out to work on any
other platform, we must keep in mind that these are still very much
proprietary.
HTH,
Jeff
Dave wrote:
>
> Dear colleagues:
>
> If this is an obvious question, I will apologize in advance for being
> so dense. I have programmed in C for several years, and have been
> studying C++ for the past several months...and am writing my first
> program with it. Everything is chugging along fine...But there is one
> question which baffles me. Am I missing something, or is there a big
> gap in the functionality of C++?
>
> It appears to me that the "new" operator in C++ always results in
> NON-RELOCATABLE block allocated in the heap...in other words it gives
> you a POINTER to a LOCKED block.
>
> Now, every personal operating system API, such as Macintosh and
> Windows, provides the ability to create HANDLES to RELOCATABLE blocks.
> This is so you don't fragment the heap like Swiss cheese...and the
> operating system's memory manager can compact the heap during
> housekeeping cycles.
>
> In fact, Windows has been so anal about this, that the ONLY way to get
> a NON-relocatable Pointer to something, is that after you allocate the
> block, you must call HLOCK(), which returns the Pointer. (We all know
> this, right?)
>
> So...in standard C++...how in the world do you get a HANDLE to
> something using the "new" operator (without doing some big silly
> kluge, like writing your own routines in every program to overload the
> "new" operator...)
>
> I can't believe that the Founding Father(s) (and/or standards
> committee) of C++ overlooked the ability to obtain a HANDLE to a
> RELOCATABLE block, or require an overloaded "new" operator, since this
> ability is so fundamentally useful in every commercial operating
> system API...
>
> But I can't find mention of HANDLES in any C++ language reference...
>
> Thanks for any explanations...
>
> --Dave
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]