0

I wanted to compile for myself openttd sources. It was using Squirell library which i could not compile because of linker error. I looked up into the code which could not be compiled and i saw weird construct which I ( and linker :D ) could not understand :

new ((void *)&_vals[i]) T(v._vals[i]);

Whole source code(line 41)

I modified the code so it looks now like that :

_vals[i] = *(new  T(v._vals[i]));

I do not know wheter i modified the code in good way or not. I hope that i did it. Game is not crashing right now so maybe there is a chance that it works well.

Could someone please say why this construct is not doing any compile time errors, just linker errors? What exactly is this code doing?

Important information : I'm using visual studio 2013.

Shoter
  • 976
  • 11
  • 23
  • 2
    [Placement new](http://stackoverflow.com/questions/222557/what-uses-are-there-for-placement-new) – AndyG Mar 05 '15 at 20:04
  • 3
    Can you show this linker error? – Drew Dormann Mar 05 '15 at 20:05
  • Reopening because this is not a duplicate. The question was also whether the modification has adverse effects. – Björn Pollex Mar 05 '15 at 20:08
  • @Shoter: Welcome to Stackoverflow. Note that linking to relevant code is not a good practice, because links tend to go stale. Please post relevant excerpts in your question (such as types of all involved variables). You should also always post the exact error messages you are getting. This makes it much easier for people to answer your question, and makes it more useful to other people with a similar problem. – Björn Pollex Mar 05 '15 at 20:12
  • Linker error : 4>e:\openttd\trunk\src\3rdparty\squirrel\squirrel\squtils.h(38): fatal error C1001: An internal error has occurred in the compiler. 4> (compiler file 'f:\dd\vctools\compiler\utc\src\p2\main.c', line 228) I have slight diffrence in line number. – Shoter Mar 05 '15 at 20:12

3 Answers3

4

It's standard placement new. You're probably missing

#include <new>
ecatmur
  • 152,476
  • 27
  • 293
  • 366
3

Your modification has introduced a memory leak. Before, the new object was constructed into already allocated memory using placement new. Now you create an object using new and then copy that into _vals. However, you never call delete on the original.

Björn Pollex
  • 75,346
  • 28
  • 201
  • 283
1

It is placement new:

new (addr) T(...)

Constructs the T object at memory address addr. Here it constructs it at the address &_vals[i], that is, it overwrites the object _vals[i]. The address gets casted to void*, i.e. a raw memory address.

This is sometimes used to re-construct an object, when it is immutable, or has no assignment operator implemented. For example

A a(1);
...
a.~A(); // needed as otherwise a would not get destructed
new (&a) A(2);
...

Makes a new A object at the same address than the old one, keeping references and pointers to it valid.

It is a low-level operation and can cause problems, i.e. with memory alignment when it is not sure that addr is suitable for the object.

The modified code instead constructs a new object on the heap, and assigns it to the existing object, and leaks it. This would not leak memory in that case:

_vals[i] = T(v._vals[i]);

The linker error is probably because there is no T::operator=(const T&), and because of that placement new was used. (For example if T contains a reference member and is immutable)

tmlen
  • 8,533
  • 5
  • 31
  • 84
  • I think that microsoft visual studio 2013 doesn't handle well placement new because it crashes the linker :/. Thank you for help! – Shoter Mar 05 '15 at 20:18
  • This is the most concise answer – SomeWittyUsername Mar 05 '15 at 20:22
  • Maybe there is a declaration `T& operator=(const T&);` in the class `T` without a definition in the `.cpp`. This is sometimes used to indicate that a method is not implemented before C++11 (which has `= delete`) (and causes linker error). Placement new probably doesn't crash the linker. – tmlen Mar 05 '15 at 20:53