Meditation, The Art of Exploitation

Thinking? At last I have discovered it--thought; this alone is inseparable from me. I am, I exist--that is certain. But for how long? For as long as I am thinking. For it could be, that were I totally to cease from thinking, I should totally cease to exist....I am, then, in the strict sense only a thing that thinks.

Wednesday, April 25, 2007

C++ stack only object

To complete the discussion on object creation constraint by memory location. We shall see how one can force object creation on stack only. Again, the code is very simple:

class A{
private:
void * operator new(size_t size) {}
};

int main(){
A a;
A * b;
A * c = new A;
}

One needs to declare a private 'operator new' in stack only bound object. The trick is this: C++ distinguishes between 'new operator' (as used in A * c = new A) and 'operator new' (declared in class A). However, beneath the hood, 'new operator' calls 'operator new' to dynamically allocate an object. Once the 'operator new' is declared as private, the built-in 'new operator' can no longer access it and such a class cannot be instantiated on heap.

C++ heap only object


> Hi all,
> All I want to achieve is restricting the object instantiation in stack
> and allowing the application to instantiate the object only in heap
> using new operator. How to achieve this?
>
> I tried out with the following code.
> Could you please give me the reason for the compilation error for the
> following code:
>
> #include < iostream>
>
> class Temp
> {
> public:
> friend void* ::operator new (size_t);
> friend void ::operator delete (void* pDel);
> private:
> Temp ()
> {
> std::cout << "Temp Ctor" <<; }
> ~Temp ()
> {
> std::cout << "Temp Dtor" <<; }
> };
>
> int
> main ()
> {
> Temp *pT = new Temp;
> delete pT;
>
> // Temp tempObj; // Should be disallowed
> return 0;
> }
>
> Compilation error received:
> ---------------------------------------
> heap.cpp: In function 'int main()':
> heap.cpp:9: error: 'Temp::Temp()' is private
> heap.cpp:22: error: within this context
> heap.cpp:13: error: 'Temp::~Temp()' is private
> heap.cpp:23: error: within this context
>
> Please help me in instantiating the Temp object only in heap, not in
> stack.
>
> thanks
> Sukumar R
>

This code is overly complicated, to prevent object creation/destruction on stack, one just needs to declare a private destructor. Think about the life time of a stack object. It's created upon entrance of the function and destroyed before leaving the function. The compiler must have access to both constructors and destructor. It's inconvenient or maybe undesirable to declare private constructors but it's always straightforward to declare a private destructor.

Tuesday, April 24, 2007

It's easy to make mistakes while coding C++

I was reading CLC++ today and found this little gem. It's got 3 glaring problems in 23 lines of C++ code.


Guys, I have the following piece of code. Could you please help me understand why
b.ToString( ) cannot be called while b.foo( ) can? When I compile I get (gcc, but visual studio gives the same pretty much). Thanks

$ g++ -Wall foo.cpp
foo.cpp: In function `int main(int, char**)':
foo.cpp:21: error: no matching function for call to `Bar::ToString()'
foo.cpp:14: note: candidates are: virtual std::string Bar::ToString(std::string&) const

#include < stdlib.h>
#include < string>
using namespace std;

template < typename> class Foo {
public:
virtual std::string ToString (std::string& pfx) const = 0;
std::string ToString ( ) const { return(ToString(std::string( ))); }
virtual void* _foo ( ) const = 0;
void* foo( ) const { return (_foo( )); }
};

class Bar: public Foo< int> {
public:
std::string ToString (std::string& pfx) const { return (std::string("test")); }
void* _foo ( ) const { return(NULL); }
};

int main (int argc, char **argv) {
Bar b;
b.foo( );
b.ToString( );
return (0);
}

Gratz, you have manged to demonstrate two C++ gotchas in your short code: binding temporaries to non-const reference and name hiding. When derived class uses same name declared in base class, the name in base class is hidden. The example below is how you fix them:

#include < stdlib.h>
#include < string>
using namespace std;

template < typename> class Foo {
public:
virtual std::string ToString (const std::string& pfx) const = 0;
std::string ToString ( ) const { return(ToString(std::string( ))); }
virtual void* _foo ( ) const = 0;
void* foo( ) const { return (_foo( )); }
virtual ~Foo(){}
};

class Bar: public Foo< int> {
public:
using Foo< int>::ToString;
std::string ToString (const std::string& pfx) const { return (std::string("test")); }
void* _foo ( ) const { return(NULL); }
};

int main (int argc, char **argv) {
Bar b;
b.foo( );
b.ToString( );
return (0);
}

Although arguably it's not an issue in this short example, but make it a habit to declare a virtual destructor in the base virtual class. It'll save a lot of headache in the future.

Friday, April 20, 2007

reference type cannot be reseated in C++

In C++, a variable can be declared as a reference to a referent object. There are some benefits with reference types, they must be initialized upon construction (note not declaration), for example,

int x;
int & rx = x;
// int & rxa = x ! Compile error: error: ‘rxa’ declared as reference but not initialized

class A {
int & rx;
A (int x): rx(x){ }
};


The first case is initialization upon construction via declaration. The 2nd case however shows that initialization only happens at construction. One can declare a reference type class member without initializing it until class object construction time.

There is a subtle implication here related to STL container types. The STL containers usually require that an object can be default constructed, copy constructed and copy assigned. When one declare a class with reference type class members, it becomes a problem how to properly initialize the reference type class members at construction time. Remember that a default constructor takes no argument, therefore one cannot initialize the class member through a constructor argument such as shown in the example above (by definition it's no longer a default constructor). One must declare a default constructor in addition to other ones that constructs with arguments. One technique is to use a global variable as a referent for reference type class members such as:
int global;
class A{
int x;
public:
A (): x(global){}
};

But this kind of coding practice is beyond style issue, what's the point of having class members that refer to a global variable that's visible to the entire code scope anyway? Since they will all refer to the same referent global object, it's also less efficient to declare a reference per object. Sadly there does not seem to be any way out of this C++ standard. Here the fix is not to use a reference type but a pointer because pointers are not required to be initialized upon construction. As one can see, the key difference between reference and pointer is 'reference is initialization upon construction', this makes reference much safer to dereference than pointers but at the same time limits its usefulness.

There is one important property of reference type. That is, reference type cannot be reseated! Once a reference type is initialized upon construction, it's bound to the referent. One cannot change the referent it's bound to through out the reference type lifetime. Often people get confused that one can assign new variables or references to a reference after its initialization, consider the following examples,

int x;
int & rx = x;
x = 3;
int y = 4;
rx = y;
int & ry = y;
rx = ry;

One may think that rx is changed to refer to different object looking at the code. But it's wrong. rx is referring to x exclusively. The value of x is changed every time rx is used as an assisgnee. Remember that reference type cannot be reseated, it's simply an alias of its referent upon its initialization. The above example is equivalent with:
int x;
int & rx = x;
x = 3;
int y = 4;
x = y;
int & ry = y;
x = ry;

Simply replace every occurrence of rx with x, and you see what's going on. As an exercise, see if you can figure out the output of the following code correctly, if you did, then reference type reseating issue is no longer a myth to you:
#include
using namespace std;

int main(){

int x = 1;
int & rx = x;
rx = 2;
cout << "x = " << y =" 3;" class="blsp-spelling-error" id="SPELLING_ERROR_28">rx = y;
cout << "x = " << class="blsp-spelling-error" id="SPELLING_ERROR_30">rx = 4;
cout << "y = " << class="blsp-spelling-error" id="SPELLING_ERROR_32">ry = y;
rx = ry;
ry = 4;
cout << "x = " << class="blsp-spelling-error" id="SPELLING_ERROR_37">cout << "y = " << y << '\n';

}

Wednesday, April 04, 2007

openmp with gcc on fedora core 5

There are many code examples using openmp, but it is less obvious exactly how you can actually compile and experiment with openmp. On fedora core 5, gcc 4.1 already has openmp support through compiler modification and openmp library. Make sure you have libgomp installed. Using an openmp example from http://www.kallipolis.com/openmp/1.html, you can compile the source code with the following command line:
g++ -fopenmp -fstrict-aliasing -fomit-frame-pointer -Wall -pedantic -ansi -g -O2 openmp_taylor.cpp -o openmp_taylor -lgomp

The important things to note here are -fopenmp (tells gcc to enable openmpp support by parsing openmpp #pragma directives) and -lgomp (the openmp library APIs).