4 Ekim 2017 Çarşamba

Static Initialization Order Fiasco

Giriş
İki static global değişken birbirlerini kullanmamalıdır. Kullanırlarsa static initialization order fiasco olabilir. Aslında aynı problem destructorlar için de mevcut. Açıklaması şöyle
Despite the name, it also applies to the order in which global objects are destructed.
Örnek
Elimizde 3 tane cpp olsun

GlobalSet.cpp şöyle olsun
#include "GlobalSet.cpp"
std::set<int> GlobalSet::s;
void* GlobalSet::addValue(int val){
    s.insert(val);
    return NULL;
}
One.cpp şöyle olsun
#include "One.h"
#include "GlobalSet.h"
void* globalset =GlobalSet::addValue (1);
Two.cpp şöyle olsun
#include "Two.h"
#include "GlobalSet.h"
void* globalset2 =GlobalSet::addValue (2);
3 dosyadaki global değişken ve metodlar birbirlerine bağlıdır. Dolayısıyla static order initialization fiasco gerçekleşir. Derleme sırasını değiştirince hata alırız.
g++ GlobalSet.cpp One.cpp Two.cpp test.cpp -o test.exe //normal
g++ One.cpp Two.cpp GlobalSet.cpp test.cpp -o test.exe //segment fault!!
Çözüm
Açıklaması şöyle. Yani static local değişken kullanmak gerekir.
The usual work-around is to substitute your static variables with functions that have a static variable in the scope, initialize, and return it.
Static1.cpp şöyle olsun
#include "Static1.hpp"
const std::string Static1::my_string = "aaa";
Static2.cpp şöyle olsun. Burada Static1.cpp'ye bağımlılık var
#include "Static2.hpp"
const std::string Static2::my_string = Static1::my_string;
Bu iki static birbirleirne bağımlı oldukları için şu kod derleme sırasına göre farklı sonuçlar verebilir.
cout << to_string(Static2::my_string == "aaa") << endl;
Çözüm için Static1.cpp'de şöyle yaparız.
std::string Static1::my_string()
{
   static const std::string my_string = "aaa";
   return my_string;
}
Static2.cpp'de şöyle yaparız.
std::string Static2::my_string()
{
   static const std::string my_string = Static1::my_string();
   return my_string;
}
Böylece kod derleme sırasına bağlı olmaksızın doğru çalışır.






Hiç yorum yok:

Yorum Gönder