最近我的公司已經開始從Visual Studio 2010升級到Visual Studio 2015的過程。我們目前遇到的問題顯然似乎源於編譯器行爲的變化。我們可以構建並運行我們的解決方案,但似乎陷入僵局(似乎只是閒置:CPU使用率接近0)。用靜態變量靜態方法重入
通過使用調試器,我們發現了一個單例對象在初始化期間依賴於自身的問題。這裏有一個非常精簡的版本:
#include <iostream>
using namespace std;
struct Singleton
{
Singleton(int n)
{
cout << "Singleton(" << n << ")" << endl;
cout << Singleton::Instance().mN << endl;
mN = n;
}
static Singleton& Instance()
{
static Singleton instance(5);
return instance;
}
int mN;
};
int main() {
cout << Singleton::Instance().mN << endl;
return 0;
}
當然,在我們的代碼有很多其他的事情怎麼回事,但是這個代碼顯示出,我們在主項目看到了同樣的行爲。在VS2010中,這會構建,運行並終止「正常」。在VS2015中,它陷入僵局。
我也嘗試過在ideone.com中使用各種版本的C++,所有這些都重現了死鎖行爲。這對我來說是合理的,這不起作用(也不應該起作用),因爲對象不應該依賴於它自己。
我更加好奇的是爲什麼在VS2010中「工作」?標準對靜態變量初始化有什麼要說的?這只是一個VS2010(可能更早)的編譯器錯誤?
更多信息:即使沒有這個具體的規定,如果它沒有可觀察到的行爲,它仍然是UB的一部分,關於一個線程可假設終止 –
非常好,這正是我想知道的。不幸的是,雖然我同意你的評估,即代碼應該被重寫,但是它帶有非常高的開發成本,我們無法承受(實際的代碼自然會更復雜)。現有的代碼庫有很多問題,比這更深遠。我們正在逐漸轉向新的架構,所以我們不會永遠陷入這樣的困境,但現在我們仍然堅持下去。 – Kyle
此外,就VS2015而言,有一種解決方法不涉及重寫有問題的代碼。使用/ Zc:threadSafeInit-強制VS2015編譯器放棄線程安全合規性和功能,與2010年的運行方式類似。顯然,這是一個可怕的黑客攻擊。 – Kyle