// now t2, t3, t4, t5 all have their member variables invalidated???
return 0;
}
Basically after creation of t7, all t2-t5 have their member variables invalidated; their mArg0 and mArg1 for example are just 0xcccccccc. However using the debugger I see that they are clearly valid up untill t7.
This is not the same output as in my main code (where the mTask = task in t2 throws an exception) but I think the cause of the error is the same
Why is this? There must be some bug with my factory/allocation scheme.
Please post actual code, it makes it much easier to find this sort of thing.
My guess is that you are using a container like std::vector and you have used enough space to cause it to resize. Whenever you add an item to a vector container it can invalidate all the pointers within it. There are other containers that don't have that property.
Please post actual code, it makes it much easier to find this sort of thing.
My guess is that you are using a container like std::vector and you have used enough space to cause it to resize. Whenever you add an item to a vector container it can invalidate all the pointers within it. There are other containers that don't have that property.
I posted a minimal code sample which reproduces this, did it not display in the post?
When I ran your code, t2-t5 aren't corrupt after t7 is created... they're corrupt as soon as they're created
[edit] because:class TestClass
{
public:
TestClass(Task task, void* funcArg, int& arg0, int& arg1) : mArg0 (arg0), mArg1(arg1)
private:
SomeArg& mArg0;
SomeArg& mArg1;<-- this reference points to...
...
TestClass* create(Task a0, void* a1, int a2, int a3)<-- this temporary stack value
{ return new T(a0, a1, a2, a3); }
The templated allocation functions appear to be taking their arguments by value. Adding a & modifier to the two argument constructor and to the final two parameters of the 4 argument constructor does not cause the behaviour you are seeing. In fact I see the behaviour you describe when the second object has been completed, as per this example:
#include "boost/function.hpp"
typedef boost::function1<void, void*> Task;
typedef int SomeArg;
class Allocator
{
public:
template<class T, typename arg0, typename arg1>
T* create(arg0 a0, arg1 a1) { return new T(a0, a1); }
$ g++ test.cpp
$ ./a.out
arguments(0x7fff264bce68, 0x7fff264bce6c)
contruct2(0x7fff264bcdb4, 0x7fff264bcdb0)
1: 1, 2, 0(0)
contruct4(0x7fff264bcd44, 0x7fff264bcd40)
1: 1, 642502160, 0(0)
2: 32767, 642502032, 1(0)
contruct2(0x7fff264bcdb4, 0x7fff264bcdb0)
1: 1, 2, 0(0)
2: 32767, 642502032, 1(0)
3: 3, 2, 0(0)
[/quote]
You can see the addresses of the constructor parameters is not that of the values on the stack, and the corruption comes as soon as the construction returns.
Modifying the allocator like so works:
class Allocator
{
public:
template<class T, typename arg0, typename arg1>
T* create(arg0 &a0, arg1 &a1) { return new T(a0, a1); }
I see.
Is there any good general solution to this? For example it's just circumstance 3rd and 4th argument are passed as references, since I intend to forward any argument, whether by value or reference, to the the created classes constructors.
I believe the simplest solution, if you cannot use perfect forwarding in C++11 (I'm not sure of how supported it is), is to overload each combination of const and non-const references.
Can I still pass arguments by value with those declarations?
[/quote]
Pass by value will go through the const reference overloads, so they should work perfectly. As the code is simple and inlined in the template body, there should be no overhead of indirect access. Const references can also bind to temporaries and literals.
Are there any other/better object construction schemes btw?
[/quote]
Apart from C++11 perfect forwarding, not that I am aware of.