I'm facing a problem using VC++ and Debug CRT with a DLL in development.
I have a struct like that, holding some references.
struct DATA
{
TA*& a;
TB*& b;
TC*& c;
TD*& d;
char** chars;
int num_chars;
private:
// because:
// DATA a;
// DATA b;
// a = b; // is impossible
DATA& operator=(const DATA&); // append " = delete;" for C++11
// Default ctor (private because struct should be manually constructed using malloc)
DATA(TA*& a, TB*& b, TC*& c, TD*& d)
: a(a),
b(b),
c(c),
d(d),
chars(NULL),
num_chars(0)
{}
};
and construct it like that:
DATA*& Get()
{
static struct DATA *data = (struct DATA*)malloc(sizeof(struct DATA));
return data;
}
now it should hold uninitialized ref-to-ptrs, which I want to init by:
void func(TA* a, TB* b, TC* c, TD* d)
{
Get()->a = a;
Get()->b = b;
Get()->c = c;
Get()->d = d;
...
}
which works for everything, but ref-to-ptrs..
I'm getting a INVALID_POINTER_WRITE_FILL_PATTERN_cdcdcdcd
on the first Get()->a = a;
when I do !analyze -v -f
using WinDbg (in a remote Kernel Debugging "kd" instance)
Thanks for your help! :)
Edit: Solution
Solution is to use the points from the correct answer.
Making the c'tor public is necessary:
struct DATA
{
TA*& a;
TB*& b;
TC*& c;
TD*& d;
char** chars;
int num_chars;
// Default ctor
DATA(TA*& a, TB*& b, TC*& c, TD*& d)
: a(a),
b(b),
c(c),
d(d),
chars(NULL),
num_chars(0)
{}
private:
// because:
// DATA a;
// DATA b;
// a = b; // is impossible
DATA& operator=(const DATA&); // append " = delete;" for C++11
};
then using placement new
to construct the struct:
DATA*& Get(...)
{
// ... some stuff, overloading, other init-method etc. to init and construct like:
static struct DATA *data =
new(malloc(sizeof(struct DATA))) DATA(...); // At least assign ALL references in the c'tor
return data;
}
then use it and maybe assign everything that's no reference:
void func(TA* a, TB* b, TC* c, TD* d)
{
Get(a, b, c, d);
Get()->chars = ...
...
}
free'ing the whole thing needs to be done explicitly by calling the d'tor and free
, because we use placement new
:
data->~DATA();
free(data);
Note that malloc()
returns uninitialized memory. C++ objects need to be constructed. The way to get an object into uninitialized memory is to use placement new (this code also adds clean-up):
#include <new>
DATA*& Get()
{
static DATA *data = new(malloc(sizeof(struct DATA))) DATA(...);
static std::unique_ptr<DATA, void(*)(DATA*)> clean(data,
[](DATA* d){
d->~DATA();
free(data);
});
return data;
}
There is no way in C++ to reseat references, i.e., they need to be set during construction. Personally, I wouldn't use malloc()
but rather a suitable allocation anyway:
static DATA* data(new DATA(...));
... or, as Jarod42 pointed out, actually
static DATA data(...);
return &data;