Why Do We Need std::addressof, If We Already Have The & Operator?

At first glance, the std::addressof method appears to be redundant. Its  output is the address of the object passed to it. It’s exactly what the & operator have been doing ever since C was developed in the early 70’s:

#include <iostream>
#include <memory>

template<typename T>
void getAddress(T t)
{
	assert( std::addressof(t) == &t);
	std::cout << "Address returned by & operator: " << std::ios::hex << &t << "\n";
	std::cout << "Address returned by addressof: " << std::ios::hex << std::addressof(t) << "\n";
}

int main()
{
	int i = 0;
	std::cout << "Getting the address of an int type \n";
	getAddress(i);
}

Getting the address of an int type:
Address returned by & operator: 20480024FC1C
Address returned by addressof: 20480024FC1C

C , however, don’t  allow operator overloading while C++ do. More specifically C++ will let you overload the & operator.  Consider instantiating the getAddress template function with the  Buffer class defined below:

#include <iostream>
#include <memory>

class Buffer
{
private:
	static const size_t buffer_size = 256;
	int bufferId;
	char buffer[buffer_size];

public:
	Buffer(int bufferId_) : bufferId(bufferId_) {}
	Buffer* operator&() { return reinterpret_cast<Buffer*> (&buffer); }  //BAD practice, only for  illustration!
};

template<typename T>
void getAddress(T t)
{
	std::cout << "Address returned by & operator: " << std::ios::hex << &t << "\n";
	std::cout << "Address returned by addressof: " << std::ios::hex << std::addressof(t) << "\n";
}

int main()
{
	Buffer b(1);
	std::cout << "Getting the address of a Buffer type: \n";
	getAddress(b);
}

Getting the address of a Buffer type:
Address returned by & operator: 20480078F50C
Address returned by addressof: 20480078F508

In the Buffer class, the & operator is (badly) overloaded and coerced to return the address of the internal  buffer as the address of the  object. The template implementation expecting a type with an accessible & operator which, it assumes,  returns the address of the object, report the wrong address.  At the same time std::addressof method returns accurately the object’s  address.

So this is why we need std::addressof. It  was introduced into  the boost library and later into the C++ 11 standard as a workaround for a potentially unreliable & operator.

When should you use the std::addressof  method?

You should use std::addressof instead of & in any template implementation taking the address of a user-defined object. Doing so is not a perfect solution as it might  cause unexpected  behavior with types relying on an overloaded & operator (some argue it is an appropriate and just  punishment for developers dabbling in this dark art) .  However, it is possible to  detect the conflict of address reporting and  template expectations in debug builds  with assert( std::addressof(t) == &t) :

template<typename T>
void getAddress(T t)
{
	assert( std::addressof(t) == &t);
	std::cout << "Address returned by & operator: " << std::ios::hex << &t << "\n";
	std::cout << "Address returned by addressof: " << std::ios::hex << std::addressof(t) << "\n";
}

This way you will at least get a heads up while you develop and test your code.

Conclusion

Even prior to C++11 ,  Overloading the & operator has been discouraged, frowned upon  and even prohibited by several C++ coding guidelines such as the one used in aircraft and medical devices software development:   MISRA-C++:2008  (section 5-3-3).  A boost library version of addressof was released in  2002 suggesting that overloading the address operator was perceived as a problem for a long while before the C++ 11 makeover. Yet, the  introduction of the std::addressof  method  into the C++11  standard  is evidence that  the C++ committee  feared too much legacy code will break if the & operator no longer allowed to be overloaded.  I guess this is one case where the jokes about C++ giving you the tools to shoot yourself in the foot are right on the nose.

terminate() The Self Destruct Function

when things have  gone horribly wrong  and there  isn’t any graceful way of dealing with the problem,  the terminate()  function acts as a  last resort.

As its  name suggests, by default,  the remedy the method offers is simply ending the program. In the default implementation, it will do so by calling abort() Stack  unwinding or object destruction are not guaranteed – It is completely up to the compiler implementation. So if your code  depends on the object destructor for any cleanups,  such as erasing temporary files,  calling terminate() might leave you cleaning the mess on your own.

Obviously calling terminate () doesn’t make  a whole lot of sense in a normal process flow. However,  it is not difficult to inadvertently create a situation where it is called indirectly.   Depending on the compiler you are using and the build type (debug or production)  your process might simply  wink out of existence with no apparent reason.

In this post,  I’ll review a few scenarios with  C++ 14 where  throwing an exception at the wrong place and time invokes terminate().

Throwing an exception without a proper exception handler :

#include <exception>
#include <iostream>

struct MyException : public std::exception
{
};

class A
{
public:
	void f()
	{
		std::cout << "exception thrown";
		throw std::exception();
	}
};

int main()
{
	A a;
	try
	{
		a.f();
	}

	catch (MyException ex)
	{
		std::cout << "exception caught";
	}
	std::cout << "exiting main()";  //Program will exits before this line is exectuted 
	return 0;
}

In this example,  The program is throwing a base class exception object but catching a subclass. Since downcasting is not implicit  and there is no catch clause to handle an std::exception, the program  ends  by calling terminate().

Throwing an exception from a function declared with  noexcept:

A function with a  noexcept  specification  mustn’t throw an exception .  The stress here is on must not   there is nothing preventing it or any of the other function it’s calling  to throw, However, if the exception is not caught,  in the function scope,  terminate is called:

#include <exception>
#include <iostream>

class A
{
public:
	void g()
	{
		std::cout << "Throwing an exception" << std::endl;
		throw std::exception();
	}
	void f() noexcept
	{
		g();
	}
};

int main()
{
	A a;
	a.f();

	std::cout << "Called f()  exiting...";  //program terminats before getting here
	return 0;
}

Throwing an exception from a destructor:

User defined destructors are implicitly declared with noexcept ,   causing them to call terminate as described above.

throwing and exception in the constructor or the destructor  of a global, static or thread-local  objects:

Assuming the class :

class A
{
public:
	A()
	{
		std::cout << "Throwing from the constructor" << std::endl;
		throw std::exception();
	}
};

and any of these instantiations of A

A g_a;  // global
A MyClass::a  a3  //static
thread_local A a1; // thread local
int main()
{
	std::cout << "Main Started";
	return 0;
}

Will cause  the program to terminate before main() is even called.
Normally constructors are allowed to throw  exceptions. But statics, global and thread-local  objects are initialized before the main() function starts, and destroyed after it exits.  So exceptions thrown  while initializing  or destroying  these objects cannot  have an in-program code catching and handling making terminate() the only logical option.

Throwing an exception from a thread function:

Since a thread has its own stack,  an  exception handler clause  must exist in the context of  the thread to correctly unwind the stack once an exception is thrown.  So failing to have an exception handler in the thread function is similar to having no handler at all causing  the program to end with terminate():

#include <iostream>
#include <thread>

void threadFunc()
{
	std::cout << "Thread: Throwing an exception" << std::endl;
	throw std::exception();
}

int main()
{
	std::cout << "Main Started" << std::endl;
	try
	{
		std::thread t1(threadFunc);
		t1.join();  //
	}
	catch (std::exception ex)
	{
		std::cout << "exception caught" << std::endl; //not called
	}
	std::cout << "Main exiting..." << std::endl; // never called
	return 0;
}
Conclusion

Thre are other ways terminate can be unwittingly triggered. Such as changing the default std::atexit  handler to a user defined method and throwing and exception for it or re-trowing an exception you never received   But, in my view,  they are less  prone to happen without putting some effort into it.

For futher reading see  chapter 15.5.1 of  the C++ standard document:   C++14 –  ISO/IEC 14882:2014,  C++ 11 –  ISO/IEC 14882:2011

 

 

sizeof: When The Whole is Greater Than The Sum Of Its Parts

Running  the program:

	#include <iostream>

	struct A
	{
		char c1;
		int i1;
		char c2;
		int i2;
	};

	int main()
	{
		std::cout << "the size of A::c1: " << sizeof(A::c1) << std::endl;
		std::cout << "the size of A::i1: " << sizeof(A::i1) << std::endl;
		std::cout << "the size of A::c2: " << sizeof(A::c2) << std::endl;
		std::cout << "the size of A::i2: " << sizeof(A::i2) << std::endl;
		std::cout << "                   --" << std::endl;
		std::cout << "Total:             " << sizeof(A::c1) + 
			sizeof(A::i1) + sizeof(A::c2) +
			sizeof(A::i2) <<  std::endl;

		std::cout << "\nThe size of A: " << sizeof(A) << std::endl;

		return 0;
	}

Generates this output:

the size of A::c1: 1
the size of A::i1: 4
the size of A::c2: 1
the size of A::i2: 4
                   --
Total:             10

The size of A: 16

(Compiled by both Linux/GCC 4.9.2  and Visual Studio 2015, using x86 CPU)

The structure A occupies 6  bytes more than the sum of its members.

the mystery thickens when we check the output for structure B having the same elements in a slightly different order:

	#include <iostream>

	struct B
	{
		char c1;
		char c2;
		int i1;
		int i2;
	};

	int main()
	{
		std::cout << "the size of B::c1: " << sizeof(B::c1) << std::endl;
		std::cout << "the size of B::i1: " << sizeof(B::i1) << std::endl;
		std::cout << "the size of B::c2: " << sizeof(B::c2) << std::endl;
		std::cout << "the size of B::i2: " << sizeof(B::i2) << std::endl;
		std::cout << "                   --" << std::endl;
		std::cout << "Total:             " << sizeof(B::c1) + 
			sizeof(B::i1) + sizeof(B::c2) +
			sizeof(B::i2) <<  std::endl;


		std::cout << "\nThe size of B: " << sizeof(B) << std::endl;

		return 0;
	}

Now the output is:

the size of B::c1: 1
the size of B::i1: 4
the size of B::c2: 1
the size of B::i2: 4
                   --
Total:             10

The size of B: 12

Just  moving  c1   deceleration caused the B structure to shrink by 4 bytes!  Yet it’s total size is  still  larger than the sum of it’s members.

why does it happen?   The hardware is  optimized to read data from memory  address which are multiples of the data size  : 4 bytes  integers (int32) are read from addresses which are multiples of 4.  Assuming the first address is 0  valid address for int32  would be 0, 4, 8, 12 .. 4n.   1 byte sized chars are read from addresses  (0,1,2,3.. n) .

In an additional constraint ,   the C++ 11  standard requires that data members are allocated in memory in the same order they are declared,  assuming they have the  same access access-specifier (private, public  protected).

It just happens that in  our  A,B structures, all the data members have public access specifier, causing the compiler to layout the member in the same  order I defined them.

For simplicity lets assume memory start with address 0:   When laying out an object instantiated from struct A,  The compiler will start with address 0  allocating that byte for  char member c1,   It then must skip addresses 1,2,3  as they are not multiples of 4  and not suitable to store  an int32 data type. So i1 get  allocated addresses 4-7.   Next,   char member c2  is assigned address 8.   The following 3 addresses are again  skipped,  and   i2 is  assigned address  12-15.
With 10 spaces occupied by actual members and 6 bytes “skipped” (the proper term is,  padding) we get the 16 bytes as the size of  structure A.

image

with Structure B we  need only two padding bytes (after allocating space for c2) so it’s final size  is 12 instead of 16:

image

Note: The developer can instruct the compiler  to store the data members with no regard for alignment,  however, it will cost heavily  in performance since the CPU will need to shuffle the bytes around after reading them.

Empty classes and classes including virtual methods, are another examples where an object is larger than it appears to be at first glance:

	#include <iostream>

	struct A
	{
		void Hi()
		{
			std::cout << "Hi" << std::endl;
		}
	};
	
	struct B
	{
		virtual void Hi()
		{
			std::cout << "Hi" << std::endl;
		}
	};

	int main()
	{
		std::cout << "the size of A: " << sizeof(A) << std::endl;
		std::cout << "the size of B: " << sizeof(B) << std::endl;
	}

Here the output is:

the size of A: 1
the size of B: 4

The size of structure A is 1  for no apparent  reason,  it has no data members,  So where did this byte come from?
Let’s suppose  we could have a class (let’s call it O)  who’s size is zero, that is sizeof(O)=0 , In that case, I could have written  this declaration :

  	struct C
   	  {
	  O o1;
	  O o2;
	  O o3;
   	 };

the compiler will have to place o1 at the first available address  – 0  and place o2 and o3 right after it.   But the size of every O  object is 0  so all objects o1,o2,o3  will all be allocated the same address – 0.  However,  different objects must have different addresses  so  zeor sized classes cannot be permitted and a class must have  a minimal size of 1 byte.

what about the 3 extra bytes added to structure B once the Hi function became virtual?
In this case having a virtual function means  including a pointer to the virtual function table aka vftable.  The pointer is a hidden member of the object accounting for the 4 bytes.

Conclusion

The size and layout of  C++ objects  are  not alway intuitive.  Assuming the location of an individual data member from its supposed layout in memory is  asking for a slow, agonizing decent into insanity. On the other hand,  paying attention to alignment considerations is a way  to pack your objects more tightly in memory.  When you need every last byte.