Today I ran into big problems tracking down the really evasive error of corruption.
I think it would not be so difficult to find if I really paid attention to the warnings, but since I did not find suitable information on why this special warning appeared, I allowed him to crawl, which was a mistake.
So, here is the alleged warning Visual Studio 2013 gives me:
warning C4316: object allocated on the heap may not be aligned 16
And it is generated when passing alignment (16) to the temporary constructor using the const reference, as shown in the following code:
class Vector {}; __declspec(align(16)) class VectorA {}; class Shape { public: Shape(const Vector& vec) {} }; class ShapeA { public: ShapeA(const VectorA& vec) : mVec(vec) {} private: VectorA mVec; }; int main(int argc, char *argv[]) { Shape* shape = new Shape(Vector());
Which raises a few questions:
Since I am not responsible for the alignment of the specified structure (it comes from the library), I can not influence it. What would be the recommended way to get around this problem?
As this warning, I assumed that it would not have a dramatic effect. But the effects that I discovered were quite dramatic and noiseless (which only appeared when passing a completely unrelated float reference to the sqlite function). (Edit: this is actually wrong, the heap was not damaged because of this) It is really as simple as: "This code will certainly cause cumulative damage, do not do this."? or is there a more complex chain of actions to trigger something like that?
One of the workarounds I was thinking about is to have a unique_ptr for the aligned object instead of having it as a direct element, but I'm a little reluctant to add unique_ptr wherever I used to have simple structures (even if it allows i use pimpl my code)
Adding
As it turned out, I subclassed the VectorA class, which provided new delete overloads to ensure proper alignment, but my own subclass did not. But the second appearance of this warning in the next paragraph is more difficult to eliminate:
Extended
Another warning situation is as follows:
__declspec(align(16)) class VectorA { void* operator new(size_t size) { void* p = _aligned_malloc(size, 16); if(p == 0) throw std::bad_alloc(); return p; } void operator delete(void *p) { VectorA* pc = static_cast<VectorA*>(p); _aligned_free(p); } }; class ShapeB { public: ShapeB() {} private: VectorA mVec; }; int main() { std::unique_ptr<BoxShapeB> shapeb = std::make_unique<BoxShapeB>(); }
It seems that my class having an alignment element, as in this example, also generates a warning when instantiating. As I said above, the way to remove a warning is to have pointers to these participants. This warning did not happen in use-cases of Visual Studio with the same exact code, so my question is: to what extent is this obviously wrong and should be avoided at all costs? that is, what should I do from the warning?
Suppose most of my classes have a common base class Object, and most of my classes have align (16) Vector as members, is it worth it to simply overload new ones and delete in this base class and forget that all my members are Vectors for pointers? Will this approach work?