This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: i386 stack missalignment on main



> > I didn't exactly follow this, but if you mean what I think you mean,
> > this doesn't work for C++, sorry.  (Or maybe someone has fixed the
> > basic problem, I might be out-of-date).
> 
> I mean a possibly overlapping binary copy of the named arguments.
> On the x86, this could look something like this:
> 
> before move:        after move:
> 
> 
> unnamed arguments   unnamed arguments
> 
> 
> ------------------  -----------------
>                     padding
> 
> named arguments     -----------------
> 
>                     named arguemnts
> ------------------
> return address
> saved stack ptr     -----------------
>                     return address
>                     saved stack ptr
> 
> 
> Is that a problem with C++ ?  If so, why?

Yes, it will break some code.  The reason is that you cannot assume that
it is safe to move an object from one position to another just with a
memmove.  It might contain interior pointers, for example.

Here's a common case.

Consider a packed bit vector class.  Let's assume that the case where
the size is <= 32 bits is common, but sometimes we need more bits than
that.  What we do is use a word within the object to store the data for
the short case, so we don't need a new/delete combination.

This is yet another example showing why C++ could use a "move object"
convention.  No core language extension is needed, rather, it would be
nice to have a "relocate" function in the standard library which by
default calls the copy constructor and destructor, but that could be
specialized for the many classes that can be reallocated more efficiently
(in this case, by adjusting the pointer).

------------------------------------------------------------------------
#include <limits.h>

class bit_vector {
public:
	static const unsigned BIW = CHAR_BIT * sizeof(unsigned);
	explicit bit_vector(unsigned size);
	~bit_vector();
	bit_vector& operator=(const bit_vector&); // NOT SHOWN
	bit_vector(const bit_vector&);
	void set_bit(unsigned pos);		// NOT SHOWN
	bool get_bit(unsigned pos) const;	// NOT SHOWN
private:
	unsigned n_words() const {
		return (width + BIW - 1) / BIW;
	}
	void set_data_ptr();
	unsigned width;
	unsigned* data_ptr;
	unsigned short_data;
};

// Set up the data pointer.  Allocate memory only for long bit vectors.
void bit_vector::set_data_ptr()
{
	if (width <= BIW)
		data_ptr = &short_data;
	else
		data_ptr = new unsigned[n_words()];
}

bit_vector::bit_vector(unsigned size)
	: width(size)
{
	set_data_ptr();
	for (unsigned i = 0; i < n_words(); i++)
		data_ptr[i] = 0;
}

bit_vector::bit_vector(const bit_vector& orig)
	: width(orig.size)
{
	set_data_ptr();
	for (unsigned i = 0; i < n_words(); i++)
		data_ptr[i] = orig.data_ptr[i];
}

bit_vector::~bit_vector()
{
	if (width > BIW)
		delete data_ptr;
}
	


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]