c – 对齐:在具有对齐成员的所有类中警告C4316

今天我通过追踪一个非常规避的腐败漏洞遇到了很多麻烦.
我想如果我真的注意到这些警告就不会那么难找到,但由于我没有找到有关为什么会弹出这个特定警告的相关信息,我让它滑动,这是一个错误.

所以这是Visual Studio 2013给我的有罪警告:

warning C4316: object allocated on the heap may not be aligned 16

当通过const引用将align(16)临时传递给构造函数时生成它,如下面的代码所示:

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
}

这带来了几个问题:

>由于我不负责所述结构的对齐(它来自一个库),我无法真正对此产生影响.解决这个问题的推荐方法是什么?
>由于这是一个警告,我猜它不会有戏剧性的效果.但是我发现的效果非常引人注目且无声(只有在将一个完全无关的浮点引用传递给sqlite函数时才出现). (编辑:这实际上是错误的,因为这个堆没有被破坏)它是否真的如此简单:“这段代码肯定会导致堆损坏,不要这样做.” ?还是有一个更复杂的行动链导致这样的事情?

我想到的一个解决方法是对对齐的对象使用unique_ptr而不是将其作为直接成员,但是我有点不愿意在之前的任何地方添加unique_ptr(即使它允许我发布我的代码)

附录

事实证明我是继承类VectorA,它确实提供了新的删除重载,确保了正确的对齐,但我自己的子类没有.但是在下一段中第二次出现这种警告更难以摆脱:

扩展

产生警告的另一种情况如下:

__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>();
}

似乎我的任何类都有一个像这个例子中的对齐成员在实例化时也会产生警告.就像我上面说的一样,删除警告的方法是指向这些成员.
在具有相同确切代码的Visual Studio的先前版本中没有出现此警告,因此我的问题是:上述明显错误到何种程度,是否应该不惜一切代价避免?即我该怎么做警告?

假设我的大多数类都有一个公共基类Object,并且我的大多数类都使用了align(16)Vector作为成员,是否值得将重载的new和delete放在这个基类中而忘记转动所有成员向量指针?这种方法有用吗?

这个问题与通过const引用传递对齐结构无关,如你所建议的那样. See this documentation of C4316.问题是您声明了对齐的结构,但没有提供处理此对齐的适当的新/删除运算符.

如果您遇到预先构建的第三方库的情况,那么您应该向其作者报告请求以解决此问题.如果你可以自己构建这个库,那么你可以自己添加提到的运算符.

相关文章
相关标签/搜索