Alf P. Steinbach said:
* Marcel Müller:
Experts know that they don't know all. The old definition of an expert is
one who has made almost every conveivable error in the field of expertise,
and learned from that. Still, also experts make mistakes, even /trivial/
newbie mistakes; the main difference is that they know it and that they
deal with it, and that they tend to more often choose paths that turn out
to not be dead-ends.
Any buggy implementation of what?
Most uses of placement new are ill-conceived attempts at premature
optimization.
I have mostly only seen such uses of placement new, but that may be
because I don't usually delve into the innards of code that deals with
memory allocation proper (like std::vector code).
STL containers are implemented by experts and very very thoroughly tested,
so that ordinary programmers don't have to deal with the things they do
inside but can rely on the safe functionality that's exposed.
I think that's an example of non-expert use, evil premature
micro-optimization using the most dangerous low-level tool available. At
least, it sounds like you're allocating 1 chunk storage for the string
data plus two ints, and rely on implicit knowledge (not dynamically
represented) in the carrier. If so, then in addition to possible
alignment bugs, that means that you /inefficiently/ have to dynamically
allocate some variable amount of storage for every different string, when
the cost of allocation is precisely what you try to avoid. ;-)
No, placement new doesn't call a constructor "directly". The constructor
arguments you pass are forwarded to a constructor, not passed directly as
in an ordinary function call. In between there's a lot going on,
including preparation of cleanup in the event that the constructor throws.
Not sure what you mean.
Below is some code and some asm interspersed at the significant line 42
Therein placement new doesnt do much just, returns the address to construct
at AFAICS.
And N.B its more obvious doing it this way than munging two types of errors
in standard new.
IOW this should help to see what exceptions can be thrown from nonplacemnt
new more clearly
thus unravelling yet another bob.
regards
Andy Little
BTW I dont think the standard explains this very well ! It makes it sound
awfully complicated....
#include <iostream>
#include <stdexcept>
#include <string>
#include <cstring>
struct my{
my()
: text(0)
{
std::cout << "Enter some text\n";
std::string str;
getline(std::cin,str);
if (str == "throw"){
throw std::logic_error("DUMMY! I TOLD YOU not to input \"throw\"");
}
text = new char [str.length()+1];
strcpy(text,str.c_str());
}
~my()
{
std::cout << "text = \"" << text << "\" in my dtor \n";
delete [] text;
}
private:
my (my const &);
my & operator = ( my const &);
char * text;
};
int main()
{
// (malloc guarantees alignment)
void * allocation = malloc(sizeof (my));
if(allocation != NULL){
//construct a my at allocation
// input at prompt "throw" to throw
my* pmy=0;
try{
pmy = new (allocation) my(); // Line 42
pmy->~my();
//ASM
; Line 42
mov esi, edi
mov DWORD PTR __$EHRec$[ebp+12], 1
call ??0my@@QAE@XZ ; my::my
; Line 43
mov esi, eax
mov BYTE PTR __$EHRec$[ebp+12], bl
mov DWORD PTR _pmy$17011[ebp], eax
call ??1my@@QAE@XZ ; my::~my
/// end ASM
pmy=0;
}
catch(std::exception & e){
std::cout << e.what();
if(pmy){
std::cout << " and throw... twas messy bad \n";
}else{
std::cout << ", ... but throw.. twas neat \n";
}
}
free(allocation);
}
}