Topic: A "Protected" base class?
Author: maxtal@Physics.usyd.edu.au (John Max Skaller)
Date: 1995/05/06 Raw View
In article <3o9fa4$75p@steel.interlog.com>,
Herb Sutter <herbs@interlog.com> wrote:
>
>Q1: How can you detect the "real" size of an object from within a base
>class? (For me, sizeof (*this) always returns the size of the base class.)
In general you cannot. The following technique works though:
class Size {
size_t size;
public:
Size(size_t x) : size(x) {}
size_t getSize()const { return size; }
};
class MyClass : public virtual Size {
MyClass( ..) : Size(sizeof(*this)), ...
Another technique is to build a table based on RTTI.
>
>Q2: Is it safe to assume that "this" always points to the beginning of the
>object's memory image (even if accessed from a base class' internal "this")?
No.
>Motivation:
>
>I've written a first-cut base class to let objects verify themselves against
>tampering (e.g., get clobbered through someone else's rogue pointer) by
>recording a hash value of the bytes physically occupied by the object. A
>derived class calls SetProtect() at the end of every member function, and
>CheckProtect() at the beginning (to see if any tampering has been detected).
you need
class Size {
void *memory; // complete objects head pointer
size_t size; // memory extent
int counter; // nested function invocation counter
hash_type hash_value;
public:
...
You need the nested function invocation counter to ensure
recursive or dynamically nested calls do NOT check
the hash value.
An alternative is to obey the following rule:
PUBLIC functions always check and set the hash value.
PUBLIC functions NEVER call other public functions.
The second rule is a very good design idea anyhow.
PUBLIC functions are never virtual.
is also a very good idea.
While you are at it, why not code and check the class
invariants as well?
--
JOHN (MAX) SKALLER, INTERNET:maxtal@suphys.physics.su.oz.au
Maxtal Pty Ltd,
81A Glebe Point Rd, GLEBE Mem: SA IT/9/22,SC22/WG21
NSW 2037, AUSTRALIA Phone: 61-2-566-2189
Author: herbs@interlog.com (Herb Sutter)
Date: 1995/05/04 Raw View
Q1: How can you detect the "real" size of an object from within a base
class? (For me, sizeof (*this) always returns the size of the base class.)
Q2: Is it safe to assume that "this" always points to the beginning of the
object's memory image (even if accessed from a base class' internal "this")?
Q3: Is it safe to assume that the memory image of the object is exactly
sizeof(*this) bytes long and that the image should not change if no data
members are manipulated?
Motivation:
I've written a first-cut base class to let objects verify themselves against
tampering (e.g., get clobbered through someone else's rogue pointer) by
recording a hash value of the bytes physically occupied by the object. A
derived class calls SetProtect() at the end of every member function, and
CheckProtect() at the beginning (to see if any tampering has been detected).
I would like classes to mix in such protection by simply publicly deriving
from the base and then calling Set/CheckProtect() as needed. The first cut
(hastily typed, uncompiled):
#ifdef DEBUG
#define DECL_SIZEOF virtual size_t Sizeof() { return sizeof(*this); };
#else
#define DECL_SIZEOF
#endif
class Protected
{
protected:
virtual size_t Sizeof() =0;
#ifdef DEBUG //----- debug version -----
protected:
void SetProtect() { _xor = CalcXor(); };
BOOL CheckProtect() { return (_xor == CalcXor()); };
private:
unsigned int CalcXor()
{
unsigned int xor = 0;
unsigned char* p = unsigned char*(this);
unsigned char* pMax = p+Sizeof();
while (p < pMax)
xor = (xor << 3) ^ unsigned int(*p);
return xor;
};
unsigned int _xor;
#else //----- non-debug version -----
protected:
void SetProtect() { };
BOOL CheckProtect() { return TRUE; };
#endif
};
// Sample usage:
class ProtectedList : public List, public Protected
{
// the usual stuff, then:
DECL_SIZEOF
}
Does it seem like I'm attempting anything obviously wrong? Can I implement
this more elegantly in current C++? And finally, is there anything in the
working paper that will let me get the "real" size of the current object
even inside a base class (allowing me to get rid of that annoying
DECL_SIZEOF)?
It's paranoid, yes, I know that, but it's also saved my bacon more times
than I can count in C programs (particularly structs in a library I released
to users, which were able to detect their having been clobbered by stray
client-code pointers).
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Herb Sutter 2228 Urwin, Ste 102 voice (416) 618-0184
Connected Object Solutions Oakville ON Canada L6L 2T2 fax (905) 847-6019
Author: rac@intrigue.com (Robert Coie)
Date: 1995/05/04 Raw View
In article <3o9fa4$75p@steel.interlog.com>, herbs@interlog.com (Herb
Sutter) wrote:
: Q1: How can you detect the "real" size of an object from within a base
: class? (For me, sizeof (*this) always returns the size of the base class.)
sizeof always operates on the static type of the object: is this what you
mean by the "size of the base class"?
: Q2: Is it safe to assume that "this" always points to the beginning of the
: object's memory image (even if accessed from a base class' internal "this")?
I am not sure what you mean here. The address of a subobject is not
always the same as the address of the fully derived object, especially
when multiple inheritance is involved. Using a technique similar to your
virtual Sizeof() function, I think you can safely assume that 'this' in an
override of a virtual function in the most derived class is the address of
the most derived object. If by "memory image" you mean the bytes
allocated by the allocation function, this is not guaranteed for an object
that is part of an array, but for your purpose I don't think this
distinction is relevant.
[code cut]
I think you will continue to need a virtual function overridden in every
class for which this checking needs to be enabled, but I don't believe
that the information provided by this function is sufficient in the
implementation above. Since 'this' in Protected::CalcXor is not
necessarily the 'this' of the ProtectedList object, I would recommend
passing back 'this' in addition to sizeof(*this) from that function.
Followups to comp.lang.c++.
: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
: Herb Sutter 2228 Urwin, Ste 102 voice (416) 618-0184
: Connected Object Solutions Oakville ON Canada L6L 2T2 fax (905) 847-6019
Robert Coie rac@intrigue.com
Implementor, Intrigue Corporation AppleLink: INTRIGUE
Author: b91926@fsgm01.fnal.gov (David Sachs)
Date: 1995/05/04 Raw View
herbs@interlog.com (Herb Sutter) writes:
>Q1: How can you detect the "real" size of an object from within a base
>class? (For me, sizeof (*this) always returns the size of the base class.)
There is no general way to do so.
>Q2: Is it safe to assume that "this" always points to the beginning of the
>object's memory image (even if accessed from a base class' internal "this")?
NO! In particular this often points to somewhere in the middle of the
object if you use multiple inheritance or virtual bases.
>Q3: Is it safe to assume that the memory image of the object is exactly
>sizeof(*this) bytes long and that the image should not change if no data
>members are manipulated?
NO
One trick you can use, if you control the entire class stucture, is
to define a virtual function that returns the actual size of the
object.
B
>~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>Herb Sutter 2228 Urwin, Ste 102 voice (416) 618-0184
>Connected Object Solutions Oakville ON Canada L6L 2T2 fax (905) 847-6019
Author: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Date: 1995/05/08 Raw View
herbs@interlog.com (Herb Sutter) writes:
>Q1: How can you detect the "real" size of an object from within a base
>class? (For me, sizeof (*this) always returns the size of the base class.)
Use a virtual Sizeof() function like you did below.
>Q2: Is it safe to assume that "this" always points to the beginning of the
>object's memory image (even if accessed from a base class' internal "this")?
No. If you have a pointer to the most derived class's `this',
and convert it to `void *', the result is guaranteed to point to the
beginning of the storage for the object, but if you do it from a
base class there are no guarantees.
>Q3: Is it safe to assume that the memory image of the object is exactly
>sizeof(*this) bytes long
Only if you compute `size(*this)' from the most derived class,
e.g. using a virtual function Sizeof() like you did below.
>and that the image should not change if no data
>members are manipulated?
I'm not sure what the working paper says about that,
but I think in practice it would be a safe assumption.
--
Fergus Henderson | I'll forgive even GNU emacs as
fjh@cs.mu.oz.au | long as gcc is available ;-)
http://www.cs.mu.oz.au/~fjh | - Linus Torvalds