Skip to main content
gamedev.net
🔒 Locked

memset this?

Started by Lazy303 Aug 27, 2003 at 6:04 AM 20 replies 2.9k views
Original Post
Lazy303
Lazy303
Is this possible? void myclass::myfunc() { memset(this,0,sizeof(*this)); }
Fruny
Fruny
It is possible. However, it is a very , very , very , very bad idea, unless you are absolutely 100% sure your class is a POD-type (basically, something that would be accepted by a C compiler).

An object may contain hidden data members above and beyond the member you have defined. For example, many (most?) implementations implement run-time dispatch (virtual functions) through a "virtual function table pointer" that is stored in the object and is used to find the actual, dynamic type of the object and the address of the virtual functions to use.

Your code would trash it. That's bad .



[ Start Here ! | How To Ask Smart Questions | Recommended C++ Books | C++ FAQ Lite | Function Ptrs | CppTips Archive ]
[ Header Files | File Format Docs | LNK2001 | C++ STL Doc | STLPort | Free C++ IDE | Boost C++ Lib | MSVC6 Lib Fixes ]


[edited by - Fruny on August 27, 2003 7:20:13 AM]
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Ready4Dis
Ready4Dis
quote:
Original post by Fruny
It is possible. However, it is a very , very , very , very bad idea, unless you are absolutely 100% sure your class is a POD-type (basically, something that would be accepted by a C compiler).

An object may contain hidden data members above and beyond the member you have defined. For example, many (most?) implementations implement run-time dispatch (virtual functions) through a "virtual function table pointer" that is stored in the object and is used to find the actual, dynamic type of the object and the address of the virtual functions to use.

Your code would trash it. That''s bad .



[ Start Here ! | How To Ask Smart Questions | Recommended C++ Books | C++ FAQ Lite | Function Ptrs | CppTips Archive ]
[ Header Files | File Format Docs | LNK2001 | C++ STL Doc | STLPort | Free C++ IDE | Boost C++ Lib | MSVC6 Lib Fixes ]


[edited by - Fruny on August 27, 2003 7:20:13 AM]


Yes, but even with virtual functions and the vtable, it would work properly, because that isn''t returned in the sizeof call . It only returns the size of the class + data members (at least a call to sizeof(myclass) does).
davepermen
davepermen
nope, sizeof has to return the full size of an object..

else

obj* x = malloc(sizeof(obj));
new (x) obj;
x->~obj();
free(x);

and similar could not work.

"take a look around" - limp bizkit
www.google.com
If that's not the help you're after then you're going to have to explain the problem better than what you have. - joanusdmentia
My Page davepermen.net | My Music on Bandcamp and on Soundcloud
Fruny
Fruny
Visual Studio 7.1


#include <iostream>

class Foo
{
public:
void Func() {}
int i;
};

class Bar
{
public:
virtual void Func() {}
int i;
};

int main()
{
std::cout << sizeof(Foo) << '' '' << offsetof(Foo,i) << std::endl;
std::cout << sizeof(Bar) << '' '' << offsetof(Bar,i) << std::endl;
}


Output

4 0
8 4


Conclusion:

Not only the size of the class changes, but the vtbl pointer is first in the object''s binary layout, which means it would *always* be trashed.


[ Start Here ! | How To Ask Smart Questions | Recommended C++ Books | C++ FAQ Lite | Function Ptrs | CppTips Archive ]
[ Header Files | File Format Docs | LNK2001 | C++ STL Doc | STLPort | Free C++ IDE | Boost C++ Lib | MSVC6 Lib Fixes ]
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
mputters
mputters


class SomeClass
{
struct
{
int a, b;
float c, d;
} laziness;

public:
SomeClass()
{
memset( &laziness, 0, sizeof(laziness) );
}

};

antareus
antareus
That seems like an AWFUL lot of work just so you can use memset on this.

If you have too many member variables then continue to split them into their own classes and such. Initializing each one to zero is more clear than a memset on the whole thing.
--God has paid us the intolerable compliment of loving us, in the deepest, most tragic, most inexorable sense.- C.S. Lewis
Shannon Barber
Shannon Barber
In a few select cases, I memset this i nthe ctor For PoD types that I want zero''d upon creation.
The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
Stary
Stary
quote:
Original post by Magmai Kai Holmlor
In a few select cases, I memset this i nthe ctor For PoD types that I want zero''d upon creation.


Uh... nit-picking maybe, but any type with a constructor is non-POD. Yeah it works, but it''s not standard C++.
daerid
daerid
Just freakin use the ctor''s initialization list. This just seems like an aweful lot of work to be lazy about something.
daerid@gmail.com
Lord Bart
Lord Bart
Hello Lazy303,

I believe what you want to do, and is completly with in the spec of ANSI C++, is use the address of first data member.
All data members of a class will be contiguous in memory with only padding added by compiler for alignment.
So if you zeroed out memory stating at the address of first declared data member it would work on all compilers. But you would have to make sure the size is correct since sizeof a class with virtual methods is aleast one poiter larger then the size of the declear data members.
As for the virtual function table pointer were this pointer is depends on compiler. But I think its almost always the at the beginning of the class, might be the this pointer address in that way compiler knows it can look at this a figure out what type of class it is.

Lord Bart
antareus
antareus
quote:
is completly with in the spec of ANSI C++

quote:
As for the virtual function table pointer were this pointer is depends on compiler.


Your two statements conflict a little.
--God has paid us the intolerable compliment of loving us, in the deepest, most tragic, most inexorable sense.- C.S. Lewis
Mage2k
Mage2k
quote:
Original post by Fruny
Conclusion:

Not only the size of the class changes, but the vtbl pointer is first in the object''s binary layout, which means it would *always* be trashed.

Actually, if I remember correctly, where the vtable pointer is placed is compiler-dependant....



peace and (trance) out

Mage
---------------------------------------------------There are 10 kinds of people in the world:Those that understand binary, and those that dont...Mage
Lord Bart
Lord Bart
Hello antareus,

Actual I don''t think there conflicting.
I believe you can be sure that all declare data members in a class are all in contiguous memory.

The virtual function pointer is really not part of a class proper, it is there as apart of how a compiler implements virtual methods. And as such it total dependent on the compiler.

But no mater what you can start at the address of the first declared data member and go to the address of the last declared data member and all other data member have to be in-between.

Also note that data member initialize in the initialization list of a constructor are initialize in the order they were declare in the class and not how they are listed in the initialization list.

Lord Bart
Fruny
Fruny
quote:
Original post by Mage2k
Actually, if I remember correctly, where the vtable pointer is placed is compiler-dependant....



Which is why I took care to specify the compiler I used.


[ Start Here ! | How To Ask Smart Questions | Recommended C++ Books | C++ FAQ Lite | Function Ptrs | CppTips Archive ]
[ Header Files | File Format Docs | LNK2001 | C++ STL Doc | STLPort | Free C++ IDE | Boost C++ Lib | MSVC6 Lib Fixes ]
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
SabreMan
SabreMan
quote:
Original post by Lazy303
Is this possible? [...]

It''s possible but it''s immoral. Memory manipulation of that sort is a direct undermining of the type-system, and throws away any guarantees that might have been in place while working with, rather than against, the type-system. In particular, you''re saying that you know more about the correct bit-representation of types than your C++ compiler. Not only that, but if you care about portability, your assumptions about bit-representations might not hold for all compilers/platforms you are interested in.

Besides the concerns over what the compiler might silently generate within your class''s layout, there are further potential problems. The question is, what leads you to believe that all-bits-zero is a valid representation for values of whatever types happen to be in your class? Even for a type as straightforward as int, the C++ Standard provides no guarantees about the relationship between int values and the corresponding bit-patterns. All-bits-zero doesn''t have to be value zero, for example. When you move to less straightforward types such as float, and then onto things like std::string, the assumptions you are making are completely blown out of the water. In turn, this presents a possible maintenance problem. If someone writes code that makes assumptions about the layout of a class, then any change to the layout can potentially affect the correctness of that code. You should try to avoid building unnecessary dependencies like that into your code, particularly when there is little to gain. I rarely see any justifiable uses of memset, memcpy, etc on these boards. The general rule should be `if you have to ask, then don''t do it''.
VizOne
VizOne
The misbelief is that zeroing out a chunk of memory will put an object into a invariant state - this is rarely the case. So folks, free you mind from this misbelief and stick to the constructor-initialization list.

Regards,
VizOne
Ready4Dis
Ready4Dis
quote:
Original post by Fruny
Visual Studio 7.1


#include <iostream>

class Foo
{
public:
void Func() {}
int i;
};

class Bar
{
public:
virtual void Func() {}
int i;
};

int main()
{
std::cout << sizeof(Foo) << ' ' << offsetof(Foo,i) << std::endl;
std::cout << sizeof(Bar) << ' ' << offsetof(Bar,i) << std::endl;
}


Output

4 0
8 4


Conclusion:

Not only the size of the class changes, but the vtbl pointer is first in the object's binary layout, which means it would *always* be trashed.


[ Start Here ! | How To Ask Smart Questions | Recommended C++ Books | C++ FAQ Lite | Function Ptrs | CppTips Archive ]
[ Header Files | File Format Docs | LNK2001 | C++ STL Doc | STLPort | Free C++ IDE | Boost C++ Lib | MSVC6 Lib Fixes ]



Conclusion is, virtual functions are returned in it's size, because it must store the address of the function, while regular functions aren't part of the size of the class.


--- Edit ---
Just wanted to say, just beacuse it's possible, doesn't mean you should do it. Just make a function called ClearVariables or something similar, and actually type out each member variable = 0 or = NULL in the case of pointers.

[edited by - Ready4Dis on August 29, 2003 7:14:47 AM]

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.