Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C++ (http://www.velocityreviews.com/forums/f39-c.html)
-   -   vtbl inheritance (http://www.velocityreviews.com/forums/t742826-vtbl-inheritance.html)

Serve Laurijssen 01-30-2011 04:14 PM

vtbl inheritance
 
Consider this code:

class RefCounted {
private: long m_nRefCount;

public: virtual ~RefCounted();
};

struct Header {
short us;
int i1;
int i2;
};

struct UnitHeader: public Header {
BYTE filler[sizeof(ULONG) - (sizeof(UnitHeader) & (sizeof(ULONG) - 1))];
};

class CHeader : public UnitHeader, public RefCounted {
};

RefCounted has a virtual destructor, UnitHeader and Header are POD structs.

CHeader inherits from UnitHeader and RefCounted.

Now consider this:

void CHeader::MakeDummy() {
memset((UnitHeader*)this, 0, sizeof(UnitHeader));
}
The 'this' pointer in CHeader is casted to UnitHeader struct and that memory
area set to zero.
But since the class inherits from a class with a virtual destructor Im not
sure this works. How does MSVC(2005) handle the Vtbl when inheriting from a
class with a vtbl?



RaZiel 01-30-2011 10:26 PM

Re: vtbl inheritance
 
On 30.01.2011 17:14, Serve Laurijssen wrote:
> Consider this code:
>
> class RefCounted {
> private: long m_nRefCount;
>
> public: virtual ~RefCounted();
> };
>
> struct Header {
> short us;
> int i1;
> int i2;
> };
>
> struct UnitHeader: public Header {
> BYTE filler[sizeof(ULONG) - (sizeof(UnitHeader) & (sizeof(ULONG) - 1))];
> };
>
> class CHeader : public UnitHeader, public RefCounted {
> };
>
> RefCounted has a virtual destructor, UnitHeader and Header are POD structs.
>
> CHeader inherits from UnitHeader and RefCounted.
>
> Now consider this:
>
> void CHeader::MakeDummy() {
> memset((UnitHeader*)this, 0, sizeof(UnitHeader));
> }
> The 'this' pointer in CHeader is casted to UnitHeader struct and that
> memory area set to zero.
> But since the class inherits from a class with a virtual destructor Im
> not sure this works. How does MSVC(2005) handle the Vtbl when inheriting
> from a class with a vtbl?
>
>


The vtbl will remain untouched, but if you are in doubt you could easily
verify by using the debugger.

- RaZ

Goran 01-31-2011 07:51 AM

Re: vtbl inheritance
 
On Jan 30, 5:14*pm, "Serve Laurijssen" <spamj...@stnyy.rrr.com> wrote:
> Consider this code:
>
> class RefCounted *{
> private: long m_nRefCount;
>
> public: *virtual ~RefCounted();
>
> };
>
> struct Header {
> * short us;
> * int * * i1;
> * int * * i2;
>
> };
>
> struct UnitHeader: public Header {
> * BYTE filler[sizeof(ULONG) - (sizeof(UnitHeader) & (sizeof(ULONG) - 1))];
>
> };
>
> class CHeader : public UnitHeader, public RefCounted {
>
> };
>
> RefCounted has a virtual destructor, UnitHeader and Header are POD structs.
>
> CHeader inherits from UnitHeader and RefCounted.
>
> Now consider this:
>
> void CHeader::MakeDummy() {
> memset((UnitHeader*)this, 0, sizeof(UnitHeader));}
>
> The 'this' pointer in CHeader is casted to UnitHeader struct and that memory
> area set to zero.
> But since the class inherits from a class with a virtual destructor Im not
> sure this works.


I, too, think this should work.

> How does MSVC(2005) handle the Vtbl when inheriting from a
> class with a vtbl?


Don't know about 2005 specifically, but 98, 2003 and 2008 do this:

class WithoutVtbl
m1
m2
....
mx

class WithVtbl
vtbl
m1
m2
....
mx

class WithoutWithVtbl : public WithoutVtbl, public WithVtbl
WithoutVtbl::m1
....
WithVtbl::vtbl
WithVtbl::m1
....

That is, VC sticks classes together, one after the other, possibly
with padding, in "order of derivation". But you should not rely on
that nor program against it. And there's no need, either. C++ language
is +/- well prepared for these situations.

That said... What you actually seem to want is a POD (Header), then a
derived POD from it (UnitHeader), then your actual object, and you
want 0-initialization of PODs. If so, you might want to try this
(discalimer: compiled with head-compiler 0.0.1 and tested with head-
test-suite 0.0.1):

UnitHeader zeroFilled();

In CHeader, you might have

CHeader::CHeader()
{
static_cast<UnitHeader&>(*this) = UnitHeader();
}

That is, you might rely on default initialization, that is provided by
the compiler when you use Type(), to get your zero bytes.

Goran.

James Kanze 01-31-2011 11:47 AM

Re: vtbl inheritance
 
On Jan 30, 4:29 pm, Leigh Johnston <le...@i42.co.uk> wrote:
> On 30/01/2011 16:14, Serve Laurijssen wrote:
> > Consider this code:


> > class RefCounted {
> > private: long m_nRefCount;


> > public: virtual ~RefCounted();
> > };


> > struct Header {
> > short us;
> > int i1;
> > int i2;
> > };


> > struct UnitHeader: public Header {
> > BYTE filler[sizeof(ULONG) - (sizeof(UnitHeader) & (sizeof(ULONG) - 1))];
> > };


> > class CHeader : public UnitHeader, public RefCounted {
> > };


> > RefCounted has a virtual destructor, UnitHeader and Header are POD structs.


> > CHeader inherits from UnitHeader and RefCounted.


> > Now consider this:


> > void CHeader::MakeDummy() {
> > memset((UnitHeader*)this, 0, sizeof(UnitHeader));
> > }
> > The 'this' pointer in CHeader is casted to UnitHeader struct and that
> > memory area set to zero.
> > But since the class inherits from a class with a virtual destructor Im
> > not sure this works. How does MSVC(2005) handle the Vtbl when inheriting
> > from a class with a vtbl?


> That should work yes as you are calling memset on a POD base sub-object
> (of type UnitHeader).


I don't think it will fail in this particular case, because of
the data types involved and their respective alignment
requirements. But in general, the actual number of bytes
occupied by UnitHeader may be less than sizeof(UnitHeader) when
UnitHeader is a base class, so brutally writing
sizeof(UnitHeader) bytes is not a safe operation. (The "empty
base class optimization" is somewhat miss-named, because it
doesn't apply to only empty base classes.)

> In VC++ the vtable pointer will be in the
> RefCounted base sub-object so will not be affected by the memset.


Really? I would have expected that it be in front of the
UnitHeader element, with another vptr in the RefCounted
subclass. (The vptr for CHeader has to point to a different
vtable than that of RefCounted.)

--
James Kanze

James Kanze 01-31-2011 12:33 PM

Re: vtbl inheritance
 
On Jan 31, 7:51 am, Goran <goran.pu...@gmail.com> wrote:
> On Jan 30, 5:14 pm, "Serve Laurijssen" <spamj...@stnyy.rrr.com> wrote:
> > Consider this code:


> > class RefCounted {
> > private: long m_nRefCount;


> > public: virtual ~RefCounted();
> > };


> > struct Header {
> > short us;
> > int i1;
> > int i2;
> > };


> > struct UnitHeader: public Header {
> > BYTE filler[sizeof(ULONG) - (sizeof(UnitHeader) & (sizeof(ULONG) - 1))];
> > };


> > class CHeader : public UnitHeader, public RefCounted {
> > };


> > RefCounted has a virtual destructor, UnitHeader and Header are POD structs.


> > CHeader inherits from UnitHeader and RefCounted.


> > Now consider this:


> > void CHeader::MakeDummy() {
> > memset((UnitHeader*)this, 0, sizeof(UnitHeader));}


> > The 'this' pointer in CHeader is casted to UnitHeader struct
> > and that memory area set to zero. But since the class
> > inherits from a class with a virtual destructor Im not sure
> > this works.


> I, too, think this should work.


It's certainly not guaranteed.

> > How does MSVC(2005) handle the Vtbl when inheriting from a
> > class with a vtbl?


> Don't know about 2005 specifically, but 98, 2003 and 2008 do this:


> class WithoutVtbl
> m1
> m2
> ...
> mx


> class WithVtbl
> vtbl
> m1
> m2
> ...
> mx


> class WithoutWithVtbl : public WithoutVtbl, public WithVtbl
> WithoutVtbl::m1
> ...
> WithVtbl::vtbl
> WithVtbl::m1
> ...


Where does it put the second vptr?

In fact, that's not what VC++ 2005 nor g++ do. Interestingly
enough, they both systematically place base classes without
virtual functions *after* those with, in order to be able to get
by with only one vptr. (This has a second effect as well: the
memset trick will never cause a problem if the class which is
doing it happens to be the last one in the order the compiler
lays them out.

[...]
> That said... What you actually seem to want is a POD (Header), then a
> derived POD from it (UnitHeader), then your actual object, and you
> want 0-initialization of PODs. If so, you might want to try this
> (discalimer: compiled with head-compiler 0.0.1 and tested with head-
> test-suite 0.0.1):


> UnitHeader zeroFilled();
>
> In CHeader, you might have
>
> CHeader::CHeader()
> {
> static_cast<UnitHeader&>(*this) = UnitHeader();
> }


Just:
CHeader::CHeader()
: UnitHeader()
{
}
should do the trick.

--
James Kanze

Paul 01-31-2011 05:05 PM

Re: vtbl inheritance
 

"Leigh Johnston" <leigh@i42.co.uk> wrote in message
news:682dnTjNkouaQ9vQnZ2dnUVZ8nCdnZ2d@giganews.com ...
> On 31/01/2011 15:58, Pete Becker wrote:
>> On 2011-01-31 10:32:53 -0500, Leigh Johnston said:
>>
>>> On 31/01/2011 15:15, Pete Becker wrote:
>>>> On 2011-01-31 09:43:33 -0500, Leigh Johnston said:
>>>>
>>>>> On 31/01/2011 11:47, James Kanze wrote:
>>>>>> On Jan 30, 4:29 pm, Leigh Johnston<le...@i42.co.uk> wrote:
>>>>>>> On 30/01/2011 16:14, Serve Laurijssen wrote:
>>>>>>>> Consider this code:
>>>>>>
>>>>>>>> class RefCounted {
>>>>>>>> private: long m_nRefCount;
>>>>>>
>>>>>>>> public: virtual ~RefCounted();
>>>>>>>> };
>>>>>>
>>>>>>>> struct Header {
>>>>>>>> short us;
>>>>>>>> int i1;
>>>>>>>> int i2;
>>>>>>>> };
>>>>>>
>>>>>>>> struct UnitHeader: public Header {
>>>>>>>> BYTE filler[sizeof(ULONG) - (sizeof(UnitHeader)& (sizeof(ULONG) -
>>>>>>>> 1))];
>>>>>>>> };
>>>>>>
>>>>>>>> class CHeader : public UnitHeader, public RefCounted {
>>>>>>>> };
>>>>>>
>>>>>>>> RefCounted has a virtual destructor, UnitHeader and Header are POD
>>>>>>>> structs.
>>>>>>
>>>>>>>> CHeader inherits from UnitHeader and RefCounted.
>>>>>>
>>>>>>>> Now consider this:
>>>>>>
>>>>>>>> void CHeader::MakeDummy() {
>>>>>>>> memset((UnitHeader*)this, 0, sizeof(UnitHeader));
>>>>>>>> }
>>>>>>>> The 'this' pointer in CHeader is casted to UnitHeader struct and
>>>>>>>> that
>>>>>>>> memory area set to zero.
>>>>>>>> But since the class inherits from a class with a virtual
>>>>>>>> destructor Im
>>>>>>>> not sure this works. How does MSVC(2005) handle the Vtbl when
>>>>>>>> inheriting
>>>>>>>> from a class with a vtbl?
>>>>>>
>>>>>>> That should work yes as you are calling memset on a POD base
>>>>>>> sub-object
>>>>>>> (of type UnitHeader).
>>>>>>
>>>>>> I don't think it will fail in this particular case, because of
>>>>>> the data types involved and their respective alignment
>>>>>> requirements. But in general, the actual number of bytes
>>>>>> occupied by UnitHeader may be less than sizeof(UnitHeader) when
>>>>>> UnitHeader is a base class, so brutally writing
>>>>>> sizeof(UnitHeader) bytes is not a safe operation. (The "empty
>>>>>> base class optimization" is somewhat miss-named, because it
>>>>>> doesn't apply to only empty base classes.)
>>>>>
>>>>> What is this nonsense? A base subobject is an object and in this case
>>>>> the object is POD and it is fine to memset a POD object with
>>>>> sizeof(POD object type) bytes.
>>>>
>>>> struct S { };
>>>>
>>>> struct T : S { int i; };
>>>>
>>>> T t;
>>>>
>>>> Clause 9 [classes]/3: "Complete objects and *member* subobjects of
>>>> class
>>>> type shall have nonzero size" [emphasis added]. So sizeof(S) is
>>>> required
>>>> to be at least 1. But when S is used as a base class of T the resulting
>>>> subobject is neither a complete object nor a member subobjct, so it is
>>>> not required to have nonzero size. That's the "empty base class
>>>> optimization". It allows objects of type T to occupy sizeof(int) bytes,
>>>> with the S subobject taking up no space. If the compiler does that,
>>>> calling memset((S*)&t, '\0', sizeof(S)) will write 1 byte into t, which
>>>> will overwrite one of the bytes of t's int member.
>>>>
>>>
>>> Fair enough but we are not dealing with empty base classes in this
>>> case (James likes to troll with mostly irrelevant corner cases) and I
>>> am assuming that it should always work when not dealing with empty
>>> base classes (you wouldn't deliberately memset an empty base class
>>> subobject). I only foresee a problem with a generic (template)
>>> solution but you should be able to employ a trick to detect an empty
>>> base class in this case.
>>>

>>
>> Okay, so when you said "A base subobject is an object and in this case
>> the object is POD and it is fine to memset a POD object with sizeof(POD
>> object type) bytes" you meant "in this case the subobject's type is not
>> empty and the empty base class optimization does not apply".
>>
>> I'm a bit concerned about "I am assuming that it should always work when
>> not dealing with empty base classes...". Assuming is dangerous. Can you
>> cite something in the language definition that requires memset to work
>> sensibly on base subobjects of non-zero size? In particular, note the
>> language about standard-layout classes in the C++0x working draft, which
>> clarifies some murky wording concerning PODs in C++03:
>>
>> A standard-layout class is a class that:
>>
>> ...
>> either has no non-static data members in the most-derived class and
>> at most one base class with non-static data members, or has no base
>> classes with non-static data mebers, ...
>>
>> ...
>> [Note: standard-layout classes are useful for communicating with code
>> written in other
>> programming languages. ...]
>>
>> The implication clearly being that assumptions about layout for
>> non-standard-layout classes are dangerous.
>>

>
> I don't know; all I know is that it is safe to call memset on POD objects
> assuming sizeof is returning something sensible (i.e. ignoring the empty
> base class optimization).
>
> Just for fun:
>
> struct a
> {
> a() : m(0x0A) {}
> virtual ~a() {}
> char m;
> };
>
> struct b_empty
> {
> };
>
> struct b_not_empty
> {
> char m;
> };
>
> template <bool DoIt>
> void memset(void* dest, int value, std::size_t size)
> {
> memset(dest, value, size);
> std::cout << "called memset\n";
> }
> template <>
> void memset<false>(void*, int, std::size_t)
> {
> std::cout << "didn't call memset\n";
> }
>
> template <typename T>
> struct c : a, T
> {
> void set()
> {
> struct empty_one : T {};
> struct empty_two : T {};
> struct empty : empty_one, empty_two {};
> memset<sizeof(empty) != sizeof(T)>((T*)this, 0x42, sizeof(T));


All this does is call an function overloaded for the evaluation of
(sizeof(empty) != sizeof(T)). T in this case is either b_empty or
b_not_empty.

> }
> };
>
>
> int main()
> {
> c<b_empty> o1;
> o1.set();
> c<b_not_empty> o2;
> o2.set();
> }
>
> :)
>

What did this prove other than the function template specailization is
dependant on sizeof(template para) ?


Paul 01-31-2011 05:14 PM

Re: vtbl inheritance
 

"Leigh Johnston" <leigh@i42.co.uk> wrote in message
news:UYydndw81v4lcdvQnZ2dnUVZ8vOdnZ2d@giganews.com ...
> On 31/01/2011 17:05, Paul wrote:
>>
>> "Leigh Johnston" <leigh@i42.co.uk> wrote in message
>> news:682dnTjNkouaQ9vQnZ2dnUVZ8nCdnZ2d@giganews.com ...
>>> On 31/01/2011 15:58, Pete Becker wrote:
>>>> On 2011-01-31 10:32:53 -0500, Leigh Johnston said:
>>>>
>>>>> On 31/01/2011 15:15, Pete Becker wrote:
>>>>>> On 2011-01-31 09:43:33 -0500, Leigh Johnston said:
>>>>>>
>>>>>>> On 31/01/2011 11:47, James Kanze wrote:
>>>>>>>> On Jan 30, 4:29 pm, Leigh Johnston<le...@i42.co.uk> wrote:
>>>>>>>>> On 30/01/2011 16:14, Serve Laurijssen wrote:
>>>>>>>>>> Consider this code:
>>>>>>>>
>>>>>>>>>> class RefCounted {
>>>>>>>>>> private: long m_nRefCount;
>>>>>>>>
>>>>>>>>>> public: virtual ~RefCounted();
>>>>>>>>>> };
>>>>>>>>
>>>>>>>>>> struct Header {
>>>>>>>>>> short us;
>>>>>>>>>> int i1;
>>>>>>>>>> int i2;
>>>>>>>>>> };
>>>>>>>>
>>>>>>>>>> struct UnitHeader: public Header {
>>>>>>>>>> BYTE filler[sizeof(ULONG) - (sizeof(UnitHeader)& (sizeof(ULONG) -
>>>>>>>>>> 1))];
>>>>>>>>>> };
>>>>>>>>
>>>>>>>>>> class CHeader : public UnitHeader, public RefCounted {
>>>>>>>>>> };
>>>>>>>>
>>>>>>>>>> RefCounted has a virtual destructor, UnitHeader and Header are
>>>>>>>>>> POD
>>>>>>>>>> structs.
>>>>>>>>
>>>>>>>>>> CHeader inherits from UnitHeader and RefCounted.
>>>>>>>>
>>>>>>>>>> Now consider this:
>>>>>>>>
>>>>>>>>>> void CHeader::MakeDummy() {
>>>>>>>>>> memset((UnitHeader*)this, 0, sizeof(UnitHeader));
>>>>>>>>>> }
>>>>>>>>>> The 'this' pointer in CHeader is casted to UnitHeader struct and
>>>>>>>>>> that
>>>>>>>>>> memory area set to zero.
>>>>>>>>>> But since the class inherits from a class with a virtual
>>>>>>>>>> destructor Im
>>>>>>>>>> not sure this works. How does MSVC(2005) handle the Vtbl when
>>>>>>>>>> inheriting
>>>>>>>>>> from a class with a vtbl?
>>>>>>>>
>>>>>>>>> That should work yes as you are calling memset on a POD base
>>>>>>>>> sub-object
>>>>>>>>> (of type UnitHeader).
>>>>>>>>
>>>>>>>> I don't think it will fail in this particular case, because of
>>>>>>>> the data types involved and their respective alignment
>>>>>>>> requirements. But in general, the actual number of bytes
>>>>>>>> occupied by UnitHeader may be less than sizeof(UnitHeader) when
>>>>>>>> UnitHeader is a base class, so brutally writing
>>>>>>>> sizeof(UnitHeader) bytes is not a safe operation. (The "empty
>>>>>>>> base class optimization" is somewhat miss-named, because it
>>>>>>>> doesn't apply to only empty base classes.)
>>>>>>>
>>>>>>> What is this nonsense? A base subobject is an object and in this
>>>>>>> case
>>>>>>> the object is POD and it is fine to memset a POD object with
>>>>>>> sizeof(POD object type) bytes.
>>>>>>
>>>>>> struct S { };
>>>>>>
>>>>>> struct T : S { int i; };
>>>>>>
>>>>>> T t;
>>>>>>
>>>>>> Clause 9 [classes]/3: "Complete objects and *member* subobjects of
>>>>>> class
>>>>>> type shall have nonzero size" [emphasis added]. So sizeof(S) is
>>>>>> required
>>>>>> to be at least 1. But when S is used as a base class of T the
>>>>>> resulting
>>>>>> subobject is neither a complete object nor a member subobjct, so it
>>>>>> is
>>>>>> not required to have nonzero size. That's the "empty base class
>>>>>> optimization". It allows objects of type T to occupy sizeof(int)
>>>>>> bytes,
>>>>>> with the S subobject taking up no space. If the compiler does that,
>>>>>> calling memset((S*)&t, '\0', sizeof(S)) will write 1 byte into t,
>>>>>> which
>>>>>> will overwrite one of the bytes of t's int member.
>>>>>>
>>>>>
>>>>> Fair enough but we are not dealing with empty base classes in this
>>>>> case (James likes to troll with mostly irrelevant corner cases) and I
>>>>> am assuming that it should always work when not dealing with empty
>>>>> base classes (you wouldn't deliberately memset an empty base class
>>>>> subobject). I only foresee a problem with a generic (template)
>>>>> solution but you should be able to employ a trick to detect an empty
>>>>> base class in this case.
>>>>>
>>>>
>>>> Okay, so when you said "A base subobject is an object and in this case
>>>> the object is POD and it is fine to memset a POD object with sizeof(POD
>>>> object type) bytes" you meant "in this case the subobject's type is not
>>>> empty and the empty base class optimization does not apply".
>>>>
>>>> I'm a bit concerned about "I am assuming that it should always work
>>>> when
>>>> not dealing with empty base classes...". Assuming is dangerous. Can you
>>>> cite something in the language definition that requires memset to work
>>>> sensibly on base subobjects of non-zero size? In particular, note the
>>>> language about standard-layout classes in the C++0x working draft,
>>>> which
>>>> clarifies some murky wording concerning PODs in C++03:
>>>>
>>>> A standard-layout class is a class that:
>>>>
>>>> ...
>>>> either has no non-static data members in the most-derived class and
>>>> at most one base class with non-static data members, or has no base
>>>> classes with non-static data mebers, ...
>>>>
>>>> ...
>>>> [Note: standard-layout classes are useful for communicating with code
>>>> written in other
>>>> programming languages. ...]
>>>>
>>>> The implication clearly being that assumptions about layout for
>>>> non-standard-layout classes are dangerous.
>>>>
>>>
>>> I don't know; all I know is that it is safe to call memset on POD
>>> objects assuming sizeof is returning something sensible (i.e. ignoring
>>> the empty base class optimization).
>>>
>>> Just for fun:
>>>
>>> struct a
>>> {
>>> a() : m(0x0A) {}
>>> virtual ~a() {}
>>> char m;
>>> };
>>>
>>> struct b_empty
>>> {
>>> };
>>>
>>> struct b_not_empty
>>> {
>>> char m;
>>> };
>>>
>>> template <bool DoIt>
>>> void memset(void* dest, int value, std::size_t size)
>>> {
>>> memset(dest, value, size);
>>> std::cout << "called memset\n";
>>> }
>>> template <>
>>> void memset<false>(void*, int, std::size_t)
>>> {
>>> std::cout << "didn't call memset\n";
>>> }
>>>
>>> template <typename T>
>>> struct c : a, T
>>> {
>>> void set()
>>> {
>>> struct empty_one : T {};
>>> struct empty_two : T {};
>>> struct empty : empty_one, empty_two {};
>>> memset<sizeof(empty) != sizeof(T)>((T*)this, 0x42, sizeof(T));

>>
>> All this does is call an function overloaded for the evaluation of
>> (sizeof(empty) != sizeof(T)). T in this case is either b_empty or
>> b_not_empty.
>>
>>> }
>>> };
>>>
>>>
>>> int main()
>>> {
>>> c<b_empty> o1;
>>> o1.set();
>>> c<b_not_empty> o2;
>>> o2.set();
>>> }
>>>
>>> :)
>>>

>> What did this prove other than the function template specailization is
>> dependant on sizeof(template para) ?
>>

>
> Until you apologize for your earlier trolling and obnoxious outbursts I
> will continue to show little respect for any of your subsequent posts;
> i.e. don't expect any answers to your questions.
>

Are you referring to the argument where you think a member function is a
member of a class and not a member of an object?
I wonder if you still actually think you are right about that. PMSL. Of
course you were wrong all the time so why should I be the one to apologise
for your wrongness?


Bo Persson 01-31-2011 06:47 PM

Re: vtbl inheritance
 
Leigh Johnston wrote:
> On 31/01/2011 12:33, James Kanze wrote:
>>
>> Just:
>> CHeader::CHeader() : UnitHeader()
>> {
>> }
>> should do the trick.
>>
>> --
>> James Kanze

>
> How individual subobjects (the bases in this case) are laid out
> relative to each other doesn't have any bearing on calling memset
> on a particular subobject. The subobject in question is POD and
> therefore does not contain a vtable pointer; memset is fine.
>
> /Leigh


It does matter that the most derived object is non-POD. That means
that you cannot use memset on it, not even if you cast the
this-pointer to a different type.

And why would you, when the initializer list does the same thing?


Bo Persson



Bo Persson 01-31-2011 07:36 PM

Re: vtbl inheritance
 
Leigh Johnston wrote:
> On 31/01/2011 18:47, Bo Persson wrote:
>> Leigh Johnston wrote:
>>> On 31/01/2011 12:33, James Kanze wrote:
>>>>
>>>> Just:
>>>> CHeader::CHeader() : UnitHeader()
>>>> {
>>>> }
>>>> should do the trick.
>>>>
>>>> --
>>>> James Kanze
>>>
>>> How individual subobjects (the bases in this case) are laid out
>>> relative to each other doesn't have any bearing on calling memset
>>> on a particular subobject. The subobject in question is POD and
>>> therefore does not contain a vtable pointer; memset is fine.
>>>
>>> /Leigh

>>
>> It does matter that the most derived object is non-POD. That means
>> that you cannot use memset on it, not even if you cast the
>> this-pointer to a different type.
>>
>> And why would you, when the initializer list does the same thing?
>>

>
> Can you please cite the part of the standard which says that a
> subobject of a non-POD object cannot be POD?
>


A member subobject can be a POD, but that is not what we have here.

Where does it say that static_cast<POD&>(*this) is a POD, when *this
is not?



Bo Persson





Paul 01-31-2011 10:47 PM

Re: vtbl inheritance
 

"Leigh Johnston" <leigh@i42.co.uk> wrote in message
news:L-qdnUpYAcc3sNrQnZ2dnUVZ8omdnZ2d@giganews.com...
> On 31/01/2011 21:18, Leigh Johnston wrote:
>> On 31/01/2011 21:11, Leigh Johnston wrote:
>>> On 31/01/2011 20:52, Paavo Helde wrote:
>>>> "Bo Persson"<bop@gmb.dk> wrote in news:8qoha5Fua2U1@mid.individual.net:
>>>>
>>>>> A member subobject can be a POD, but that is not what we have here.
>>>>>
>>>>> Where does it say that static_cast<POD&>(*this) is a POD, when *this
>>>>> is not?
>>>>
>>>> Right, the standard has carefully excluded base class subobject POD-s
>>>> from
>>>> memcpy guarantees. I wonder if this is only done so in order to be
>>>> able to
>>>> call empty structs PODs?
>>>>
>>>
>>> Are you being sarcastic? My antenna cannot tell today. :D If not
>>> whereabouts in the standard is the exclusion?
>>>

>>
>> Never mind I think I have found it:
>>
>> 3.9/2:
>>
>> For any trivially copyable type T, if two pointers to T point to
>> distinct T objects obj1 and obj2, where
>> neither obj1 nor obj2 is a base-class subobject, if the underlying bytes
>> (1.7) making up obj1 are copied
>> into obj2,42 obj2 shall subsequently hold the same value as obj1. [
>> Example:
>> 41) By using, for example, the library functions (17.6.1.2) std::memcpy
>> or std::memmove.
>> 42) By using, for example, the library functions (17.6.1.2) std::memcpy
>> or std::memmove.
>> § 3.9 72
>>
>> c ISO/IEC N3225=10-0215
>> T* t1p;
>> T* t2p;
>> // provided that t2p points to an initialized object ...
>> std::memcpy(t1p, t2p, sizeof(T));
>> // at this point, every subobject of trivially copyable type in *t1p
>> contains
>> // the same value as the corresponding subobject in *t2p
>> —end example ]
>>
>> I think I might owe James a second apology of the month.
>>

>
> Unfortunately I tend to mostly call on my own experience a lot of which is
> Microsoft/VC++; so for example Microsoft's afx.h (part of MFC) has the
> following beauty:
>
> // zero fill everything after the vtbl pointer
> #define AFX_ZERO_INIT_OBJECT(base_class) \
> memset(((base_class*)this)+1, 0, sizeof(*this) - sizeof(class
> base_class));
>
> So Microsoft seem to have no problem with calling memset on parts of
> non-PODs; this is obviously very poor even if it does work on VC++.
>
> So yeah James you seem to be correct and I apologize.
>
> /Leigh


You don't half talk some nonsense dude.



All times are GMT. The time now is 03:08 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.