C++ Warning

When I compile the code below, why do I get this warning:
Point.cpp(29): Warning! W549: (col 31) ‘sizeof’ operand contains compiler
generated information

If I remove the virtual fonction abc() then I don’t have that warning
anymore. I don’t understand the logic being this warning?


#include <stdio.h>
class dummy {
public:
int a;
virtual abc(void);

};


class foo : public dummy
{
public:
Point() {};
};

void main(void) {
foo p;
printf(“sizeof %d\n”, sizeof ( p ) );
}

  • Mario

In article <8vdu5c$4pi$1@nntp.qnx.com>, mcharest@zinformatic.com says…

When I compile the code below, why do I get this warning:
Point.cpp(29): Warning! W549: (col 31) ‘sizeof’ operand contains compiler
generated information

If I remove the virtual fonction abc() then I don’t have that warning
anymore. I don’t understand the logic being this warning?

Mario:

I believe that the compiler inserts a pointer for each virtual function
producing an array of pointers that can be redirected in case the virtual
function is re-defined. IMHO, the warning is telling you that the size of the
object will be larger than the “obvious” sum of its data elements.

#include <stdio.h
class dummy {
public:
int a;
virtual abc(void);

};


class foo : public dummy
{
public:
Point() {};
};

void main(void) {
foo p;
printf(“sizeof %d\n”, sizeof ( p ) );
}

  • Mario

“Dean Douthat” <ddouthat@faac.com> wrote in message
news:8vduos$3d6$1@inn.qnx.com

In article <8vdu5c$4pi$> 1@nntp.qnx.com> >, > mcharest@zinformatic.com > says…


When I compile the code below, why do I get this warning:
Point.cpp(29): Warning! W549: (col 31) ‘sizeof’ operand contains compiler
generated information

If I remove the virtual fonction abc() then I don’t have that warning
anymore. I don’t understand the logic being this warning?

Mario:

I believe that the compiler inserts a pointer for each virtual function
producing an array of pointers that can be redirected in case the virtual
function is re-defined. IMHO, the warning is telling you that the size of
the
object will be larger than the “obvious” sum of its data elements.

The W549 description says:
The type used in the sizeof() operand contains compiler-generated
information. Clearing a struct with a call to memset() would invalidate all
of this information.

It’s the mention of the memset that really confuses me. The strangest
thing is that if I look at the assembly code the sizeof is hardcoded
it not generated at run time. In this perticula case a memset
wouldn’t cause any problem with the sizeof().

I’m not very experience with C++. Is getting sizeof() of a class
that has a base class with virtual function a no-no???

#include <stdio.h
class dummy {
public:
int a;
virtual abc(void);

};


class foo : public dummy
{
public:
Point() {};
};

void main(void) {
foo p;
printf(“sizeof %d\n”, sizeof ( p ) );
}

  • Mario
    \

Mario Charest <mcharest@void_zinformatic.com> wrote:

The W549 description says:
The type used in the sizeof() operand contains compiler-generated
information. Clearing a struct with a call to memset() would invalidate all
of this information.

It’s the mention of the memset that really confuses me. The strangest
thing is that if I look at the assembly code the sizeof is hardcoded
it not generated at run time. In this perticula case a memset
wouldn’t cause any problem with the sizeof().

I’m not very experience with C++. Is getting sizeof() of a class
that has a base class with virtual function a no-no???

Yes. Basically anything that you want to do with a sizeof() will cause
something bad to happen if there’s compiler-generated information
(i.e. virtual function tables) in the object. The compiler is just
gently letting you know that you’re about to screw up. Consider the
memset. If you do a “memset(&obj, 0, sizeof(obj));”, you’re going to
clear the virtual function table pointer as well as the user fields.
The code will then blow up with a SIGSEGV the next time you try to use
a virtual function with that object (since it’s going to indirect through
a NULL pointer). Similar bad things happen with any other use of the
sizeof() information (aside from just printing it out as you did in your
test program :slight_smile:.


Brian Stecher (bstecher@qnx.com) QNX Software Systems, Ltd.
phone: +1 (613) 591-0931 (voice) 175 Terence Matthews Cr.
+1 (613) 591-3579 (fax) Kanata, Ontario, Canada K2M 1W8

In article <8ve129$61j$1@nntp.qnx.com>,
Brian Stecher <bstecher@qnx.com> wrote:

Mario Charest <mcharest@void_zinformatic.com> wrote:
The W549 description says:
The type used in the sizeof() operand contains compiler-generated
information. Clearing a struct with a call to memset() would invalidate all
of this information.

It’s the mention of the memset that really confuses me. The strangest
thing is that if I look at the assembly code the sizeof is hardcoded
it not generated at run time. In this perticula case a memset
wouldn’t cause any problem with the sizeof().

I’m not very experience with C++. Is getting sizeof() of a class
that has a base class with virtual function a no-no???

Yes. Basically anything that you want to do with a sizeof() will cause
something bad to happen if there’s compiler-generated information
(i.e. virtual function tables) in the object. The compiler is just
gently letting you know that you’re about to screw up. Consider the
memset. If you do a “memset(&obj, 0, sizeof(obj));”, you’re going to
clear the virtual function table pointer as well as the user fields.
The code will then blow up with a SIGSEGV the next time you try to use
a virtual function with that object (since it’s going to indirect through
a NULL pointer). Similar bad things happen with any other use of the
sizeof() information (aside from just printing it out as you did in your
test program > :slight_smile:> .

Would this just be because it’s a “struct”? Presumably – as has been
pointed out – most of the interesting things you do with sizeof()
can’t be safely done on the vtable, and the assumption is that since
you defined the object with a C structure, you are doing C code within
C++. If that’s the case, maybe it won’t issue a warning with class
followed by a public access specifier.


Brian Stecher (> bstecher@qnx.com> ) QNX Software Systems, Ltd.
phone: +1 (613) 591-0931 (voice) 175 Terence Matthews Cr.
+1 (613) 591-3579 (fax) Kanata, Ontario, Canada K2M 1W8

Steve Furr email: furr@qnx.com
QNX Software Systems, Ltd.

Steve Furr <furr@qnx.com> wrote:

Would this just be because it’s a “struct”? Presumably – as has been
pointed out – most of the interesting things you do with sizeof()
can’t be safely done on the vtable, and the assumption is that since
you defined the object with a C structure, you are doing C code within
C++. If that’s the case, maybe it won’t issue a warning with class
followed by a public access specifier.

Nope. Whether the object is declared as a “struct” or a “class” doesn’t
matter. The determining criteria is if you apply a sizeof() operator
on something that contains compiler generated internal information.
A “class” or “struct” with just POD (plain old data) will not cause
the warning to come out.


Brian Stecher (bstecher@qnx.com) QNX Software Systems, Ltd.
phone: +1 (613) 591-0931 (voice) 175 Terence Matthews Cr.
+1 (613) 591-3579 (fax) Kanata, Ontario, Canada K2M 1W8

Ok I understand.

The code I’m stumbling on is

template
inline T* allocate ( ptrdiff_t size, T* ) {

T* tmp = (T*) (::operator new ((size_t) (size * sizeof( T ) )));

So I guess it shoul be replace by

T* tmp = (T*) (::operator new ((size_t) T[size] ) ));

This doesn’t create anywarning, but is it the “right” way?

“Brian Stecher” <bstecher@qnx.com> wrote in message
news:8ve129$61j$1@nntp.qnx.com

Mario Charest <mcharest@void_zinformatic.com> wrote:
The W549 description says:
The type used in the sizeof() operand contains compiler-generated
information. Clearing a struct with a call to memset() would invalidate
all
of this information.

It’s the mention of the memset that really confuses me. The strangest
thing is that if I look at the assembly code the sizeof is hardcoded
it not generated at run time. In this perticula case a memset
wouldn’t cause any problem with the sizeof().

I’m not very experience with C++. Is getting sizeof() of a class
that has a base class with virtual function a no-no???

Yes. Basically anything that you want to do with a sizeof() will cause
something bad to happen if there’s compiler-generated information
(i.e. virtual function tables) in the object. The compiler is just
gently letting you know that you’re about to screw up. Consider the
memset. If you do a “memset(&obj, 0, sizeof(obj));”, you’re going to
clear the virtual function table pointer as well as the user fields.
The code will then blow up with a SIGSEGV the next time you try to use
a virtual function with that object (since it’s going to indirect through
a NULL pointer). Similar bad things happen with any other use of the
sizeof() information (aside from just printing it out as you did in your
test program > :slight_smile:> .


Brian Stecher (> bstecher@qnx.com> ) QNX Software Systems, Ltd.
phone: +1 (613) 591-0931 (voice) 175 Terence Matthews Cr.
+1 (613) 591-3579 (fax) Kanata, Ontario, Canada K2M
1W8

I’m not very experience with C++. Is getting sizeof() of a class
that has a base class with virtual function a no-no???

No your problem is that you do not take the size of the class, but the size
of an instance of the class. Use sizeof(foo) insted.

And remember that sizeof is handled at compile time not runtime.

Martin Tilsted

“Martin Tilsted” <Tiller@adr.dk> wrote in message
news:8veihn$mls$1@inn.qnx.com

I’m not very experience with C++. Is getting sizeof() of a class
that has a base class with virtual function a no-no???

No your problem is that you do not take the size of the class, but the
size
of an instance of the class. Use sizeof(foo) insted.

I don’t see why it would make a difference; as a matter for fact
doing a sizeof(foo) gives out the same results. That’s not the root
of the “problem”.

And remember that sizeof is handled at compile time not runtime.

That’s the whole point, in this case it’s not :wink: That is what
the compiler is warning me about. It’s telling me the size information
is store within the class, thus it can be mistakenly erased.

Martin Tilsted

Mario Charest <mcharest@void_zinformatic.com> wrote in message
news:8vf59e$grn$1@nntp.qnx.com

And remember that sizeof is handled at compile time not runtime.

That’s the whole point, in this case it’s not > :wink: > That is what
the compiler is warning me about. It’s telling me the size information
is store within the class, thus it can be mistakenly erased.

You mentioned in your other message it is hard-coded in the assembly, thus

was at least in this case, generated at compile.

I don’t think its trying to tell you size information is stored in the
class, its telling you “compiler-generated information” (i.e. the vtable) is
stored in the memory for the object. It is warning you not to clear with
memset or anything similar, or you will destroy the vtable and blow up your
next virtual method call.

As far as syntax goes, I don’t know enough about internals of vtables, but I
would fear that
n*sizeof(T) might not even equal
sizeof(T[n]) in every case.
Wouldn’t the function pointers be the same for each member of the array,
with only the hidden “this” parameter changing, and thus be subject to
optimization by storing only once?

I would be careful to use the one you actually mean.

=Dave

In article <8vfejv$jfg$1@inn.qnx.com>,
Dave Lees <dave40@@rochester.rr.com> wrote:

Mario Charest <mcharest@void_zinformatic.com> wrote in message
news:8vf59e$grn$> 1@nntp.qnx.com> …

And remember that sizeof is handled at compile time not runtime.

That’s the whole point, in this case it’s not > :wink: > That is what
the compiler is warning me about. It’s telling me the size information
is store within the class, thus it can be mistakenly erased.

You mentioned in your other message it is hard-coded in the assembly, thus
was at least in this case, generated at compile.

I don’t think its trying to tell you size information is stored in the
class, its telling you “compiler-generated information” (i.e. the vtable) is
stored in the memory for the object. It is warning you not to clear with
memset or anything similar, or you will destroy the vtable and blow up your
next virtual method call.

Bingo! The compiler will always know the correct sizeof since you can only
do it on a complete type definition, so it will know the size of the
vtable generated. The issue is that the warning notifies the programmer
to be wary of memset and its ilk.

As far as syntax goes, I don’t know enough about internals of vtables, but I
would fear that
n*sizeof(T) might not even equal
sizeof(T[n]) in every case.
Wouldn’t the function pointers be the same for each member of the array,
with only the hidden “this” parameter changing, and thus be subject to
optimization by storing only once?

Well, it would be compiler dependent. I’m not sure if an optimization
promoting the vtable to the array itself would be legal – presumably not –
but I doubt if such an optimization would be practical in any case.
The reason I don’t think it would be legal is that it could only be
possible if you had a notion of “final” classes, such as Java has.
Otherwise, the array is still polymorphic – any element could be a
sub-class if T is a pointer. In such a case, each element could have a
different vtable. (Thinking about it further, if the array were determined
not to be pointers, the compiler could do something, but only for that
highly specific case).

I would be careful to use the one you actually mean.

Which means that for operator new(), you really do have to use sizeof
to obtain enough memory for the vtable. Can you do a sizeof(T[n])
in C++ – where n is not a constant? I remember C++ sizeof() to be a little
more flexible – allowing type declarations in the expression – but I
don’t know if it goes that far. That would make sizeof(T[n]) the correct
thing to do. Otherwise, you have no choice but to do sizeof(T)*n,
because T might be a pointer.

By the way, location of the vtable is a damned-if-you-do-damned-
if-you-don’t sort of issue. If the vtable is at the start of the
object, you can easily trash it with reinterpret casts; if it’s at the
end of an object with an array at the end, you can easily trash it
if you don’t do correct bounds checking. I experienced the latter
in looking at horrible C++ device code that got plopped on our doorstep.
(Watcom puts the vtable at the end). I would lean towards the former,
because it’s a little more obvious when it happens.

=Dave

Steve Furr email: furr@qnx.com
QNX Software Systems, Ltd.