A short way to initialize a memory block with magic numbers

A few examples of what I mean:

typedef struct SOME_STRUCT { unsigned int x1; unsigned int x2; unsigned int x3; unsigned int x4; // What I expected would work, but doesn't; the 2nd parameter gets // turned into an 8-bit quantity at some point within memset SOME_STRUCT() { memset( this, 0xFEEDFACE, sizeof( *this ) ); } // Something that worked, but seems hokey/hackish SOME_STRUCT() { unsigned int *me = (unsigned int *)this; for( int ii = 0; ii < sizeof(*this)/sizeof(*me); ++ii ) { me[ii] = 0xFEEDFACE; } } // The far-more-verbose-but-C++-way-of-doing-it // This works, but doesn't lend itself very well // to being a drop-in way to pull this off on // any struct. SOME_STRUCT() : x1( 0xFEEDFACE ) , x2( 0XFEEDFACE ) , x3( 0XFEEDFACE ) , x4( 0XFEEDFACE ) {} // This would work, but I figured there would be a standard // function that would alleviate the need to do it myself SOME_STRUCT() { my_memset( this, 0xFEEDFACE, sizeof(*this) ); } } 

I can't use valgrind here, and my options are limited in relation to the various debug libraries that I have access to - that's why I do it myself for this one-time case.

+4
source share
7 answers

Here is a partial example of the safe use of std::generate() :

 #include <algorithm> struct Wizard { size_t i; static unsigned char magic[4]; Wizard() : i(0) {} unsigned char operator()() { size_t j = i++; i %= sizeof(magic); // Not strictly necessary due to wrapping. return magic[j]; } }; unsigned char Wizard::magic[4] = {0xDE,0xAD,0xBE,0xEF}; std::generate(reinterpret_cast<unsigned char*>(this), reinterpret_cast<unsigned char*>(this) + sizeof(*this), Wizard()); 

(Of course, the judgment may or may not be correct, depending on how you look and what you expect to see when you do!)

+4
source

I would declare this constructor:

 SOME_STRUCT( unsigned int magic) : x1 (magic), x2 (magic), x3 (magic), x4 (magic) {} 

This is very similar to your third option and seems to be a natural C ++ way.

+2
source

A point not made by others is:

I think this is unsafe for Non-POD types. Oddly enough, adding initialization to the constructor makes it unnecessary. So I suggest a freestanding function that checks POD-natic statically (the sample uses C ++ 0x type_traits , but you can also use Boost)

 #include <iostream> #include <type_traits> template <typename T> typename std::enable_if<std::is_pod<T>::value>::type* FeedFace(T& v) { static const unsigned char MAGIC[] = { 0xFE, 0xED, 0xFA, 0xCE }; unsigned char *me = reinterpret_cast<unsigned char *>(&v); for( size_t ii = 0; ii < sizeof(T)/sizeof(unsigned char); ++ii ) me[ii] = MAGIC[ii % sizeof(MAGIC)/sizeof(unsigned char)]; } struct Pod { char data[37]; }; struct NonPod : Pod { virtual ~NonPod() { } }; int main() { Pod pod; FeedFace(pod); NonPod nonpod; // FeedFace(nonpod); // fails to compile (no matching function call) return 0; } 
+2
source

I assume this allows for unpleasant hacker material, for example:

 #include <iomanip> #include <iostream> #include <algorithm> using namespace std; int main(void) { struct SOME_STRUCT { unsigned int x1; unsigned int x2; unsigned int x3; unsigned int x4; } foo; fill(reinterpret_cast<unsigned int *>(&foo), reinterpret_cast<unsigned int *>(&foo) + sizeof(foo) / sizeof(unsigned int), (unsigned int)0xDEADBEEF); cout << foo.x1 << endl; cout << foo.x2 << endl; cout << foo.x3 << endl; cout << foo.x4 << endl; return (0); } 

It basically breaks std :: fill () with pointers.

+1
source

You can reinterpret_cast this as a char* , and then use std::generate with a predicate that rotates around the values ​​you need. If I get time later, I will try to jot down the code.

Also, did you consider, for example, the malloc library for checking LD_PRELOAD memory?

+1
source

Here is another hacker method.

 SOME_STRUCT() { x1 = 0xFEEDFACE; memmove(&(this->x2), this, sizeof(*this)-sizeof(x1)); } 
0
source

Even if your attempt at memset() did work, it makes assumptions about packing the structure and therefore is not guaranteed to be correct. There is no programmatic way to iterate through structure members and assign them in C or C ++. Therefore, you need to be content with appointing members individually. Having said that, if you feel that you are comfortable with the layout of the memory structure and do not need to worry about portable code, you can just as easily initialize it with a for loop.

 unsigned int i, *ar = (unsigned int *)&my_struct; for (i = 0; i < sizeof(my_struct) / sizeof(unsigned int); i++) { ar[i] = 0xdeadbeef; } 
0
source

All Articles