Re: Possible to partially free an object?
Joseph Garvin schrieb:
{ clc++m banner removed; you should remove it yourself. In addition,
please avoid top-posting; it is discouraged in the group. -mod }
I don't think my question was clear. Assume I have a POD type:
struct foo {
int x;
char y;
float z;
};
And a very similar struct minus one member:
struct bar {
int x;
char y;
};
Then I want to do this:
foo* test = malloc(sizeof(foo));
// ... do some stuff with test
// now I'd like to replace the foo object stored at test with a bar
object
bar* test2 = (bar *)test;
char* area_to_delete = (char *)test + sizeof(bar);
free((char[sizeof(foo) - sizeof(bar)])area_to_delete);
Will that ever explode?
Yes. This won't work.
I realize I asked for class objects and delete/
new, but given that my classes have no vtbl and no multiple
inheritance, I'm guessing that the compiler will usually pick the same
layout as a POD type.
It's not only a question of how the compiler lays out the objects, but
also how the operating system manages memory. malloc() returns a memory
block, and this block must be released as one single block, not as two
separate blocks.
In a typical implementation, malloc(s) will reserve s + sizeof(size_t)
bytes of memory, will store the size of the memory at the start of the
memory block it got, and will return a pointer to memory +
sizeof(size_t). free() will grab this size from in front of the memory
block, and knows by that its size. This implementation is legitimate,
but you would break it.
Let me add a "war time story" here: In AmigaOs, it was possible to do
exactly that, namely to release N bytes of memory out of a block of M>N
bytes allocated - you had to keep track of the size yourself, and it
"worked" provided N was a multiple of some magic constant (IIRC, eight).
One specific system library made use of this feature, to "optimize the
memory usage". This caused nothing but grief in later code - debuggers,
memory trace methods, all of them had to contain special "kludges" to
keep this code working. Finally, in the next major release, this
nonsense got removed.
In short: *DO NO TO DO THIS*.
If you want to release "extra information", make a contain a pointer to
b, and then release the memory pointed to by b, or build a "super
object" that holds pointers to a and b, and hide the pointers behind an
interface.
So long,
Thomas
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]