Alignment: Warning C4316 in all classes that have aligned elements

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()); // ok ShapeA* shapea = new ShapeA(VectorA()); // warning C4316: // object allocated on the heap may not be aligned 16 } 

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?

+6
source share
2 answers

This problem is not related to passing the aligned structure by const link or not, as you suggest. See this C4316 documentation . The problem is that you are declaring the aligned structure, but you are not providing the appropriate new / delete statements that handle this alignment.

If you get a situation with a third-party library that was previously built, then IMHO you should inform the authors about this to solve this problem. If you can create this library yourself, you can add the mentioned operators yourself.

+2
source

So, after a short conversation with Dr. Memory and a session of general problem solving turns out:

  • The heap was not damaged due to alignment problems. This means that I still do not know to what extent this warning should be alarming, but I decided to find a solution to solve it anyway:

  • To avoid this warning, I used the following solution, which gives me satisfaction: create an Align16 class that overloads all new and deleting operators to use _aligned_malloc and _aligned_free. Then each class that includes the aligned element must inherit from Align16 to warn it. I understand that this is not portable due to _aligned_malloc, so in case I want my code to be portable, Bullet Physics has a special implementation that works in its memory allocators, which I can postpone if necessary.

+1
source

All Articles