我今天遇到了很多麻煩,跟蹤了一個真正逃避腐敗的錯誤。
我想如果我真的注意到了警告,我不會很難找到它,但是因爲我沒有找到相關信息,說明爲什麼這個特定的警告彈出,我讓它滑動,這是一個錯誤。對齊方式:警告C4316在所有課程中有對齊的成員
因此,這裏的牽連警告的Visual Studio 2013給我:
warning C4316: object allocated on the heap may not be aligned 16
並將它傳遞的對齊(16)臨時當通過const引用一個構造函數,如下面的代碼生成演示了:
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
}
這帶來幾個問題:
一我不負責所述結構的對齊(它來自一個庫),我無法真正對此產生影響。解決此問題的建議方法是什麼?
由於這是一個警告,我猜測它不會有戲劇性的效果。但是我發現的效果非常戲劇化和沉默(這隻會在將一個完全不相關的float引用傳遞給sqlite函數時出現)。(編輯:這實際上是錯誤的,堆沒有因此而被破壞)是否真的如此簡單:「此代碼肯定會導致堆損壞,不要這樣做。」 ?或者是否有更復雜的行爲鏈來引起這樣的事情?我想到的
一個解決辦法是有一個的unique_ptr來對齊對象,而不是有它作爲一個直接的成員,但我有點捨不得無處不添加的unique_ptr我收到平原結構(即使它讓我PIMPL我的代碼)
附錄
事實證明我是繼承類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放在這個基類中,而忘記了把我的所有成員矢量指向指針?這種方法會起作用嗎?
是的,你是對的,它並不是因爲圖書館沒有提供新的/刪除,而是因爲我將它子類化,並沒有在我自己的子類中提供它們。但第二個問題仍然存在,所以我將重新制定。 – MONK
將對齊的類作爲其他類中的成員將生成警告(與第一個相反,即使在定義新的刪除過載以確保對齊時也會如此) – MONK
@MONK我認爲第二個問題與第一個類似。在第一個中,你繼承了對齊的結構並需要適當的操作符。我想第二種情況是一樣的。但這只是一個猜測。 – Bogdan