The problem: I am trying to allocate memory for an array of std::string
, then using new(...)[]()
to initialize it. Then I try to assign values to the array elements and this causes the application to crash (Access violation). Question is: Am I missing some compiler flag or something obvious?
Compiling this with
cl.exe /DEBUG /EHsc /MTd /Zi test.cc
produces an executable that crashes (tested in VS 2017 and VS 2012). On a side note it works as expected on Linux with GCC.
#include <iostream>
#include <string>
struct S {
int a,b;
S() : a(99), b(299) {}
S & operator=(const char * rhs) { a = 100; b = 300; return *this; }
};
std::ostream & operator<<(std::ostream & os, const S & s) { os << "(" << s.a << "," << s.b << ")"; return os; }
typedef std::string T;
//typedef S T;
int main(int argc, char ** argv) {
size_t N = 100;
std::allocator<T> mem;
T * data = mem.allocate(N);
new(data)T[N]();
for (ptrdiff_t i = 0; i < N; ++i)
data[i] = "HELLO WORLD";
for (ptrdiff_t i = 0; i < N; ++i)
std::cout << data[i] << std::endl;
}
I tried using the other typedef
, and in that case the initialization works exactly as expected.
EDIT: I see the same crash if I use C calloc
for allocation instead of std::allocator
.
SOLVED. It turns out that the problem is this: The C++ standard says that the new T[N]
expression allocates at least sizeof(T)*N
bytes. Visual C allocates an extra overhead. The placement new new(ptr)T[N]
assumes that the extra overhead is available in ptr
.
The solution from the answer below is to loop and construct each item separately.