ProgramlamaKıdemli C++ Geliştirici

C++'deki 'One Definition Rule (ODR)' sorununu açıklayın. Büyük projeleri nasıl etkiler ve ihlallerden nasıl kaçınılır?

Hintsage yapay zeka asistanı ile mülakatları geçin

Cevap

One Definition Rule (ODR), C++'in temel bir kuralıdır ve programın tümü (tüm çeviri birimleri) içerisinde her nesne, işlev veya sınıf için tam olarak bir tanımlama (definition) olmasını gerektirir.

ODR, aşağıdaki durumlarda ihlal edilir:

  • Farklı .cpp dosyalarında farklı kodlarla bir işlev/sınıfın birden fazla tanımı varsa.
  • Inline işlevi veya şablon, farklı bağlantı noktalarında farklı tanımlara sahipse.

Bu, yakalanması zor, öngörülemez hatalara, hatalı bağlantıya veya daha kötüsü, programın derleme biçimine bağlı olarak farklı davranmasına yol açar.

Neden ihlal edilir:

Büyük projelerde genellikle .h dosyaları versiyon kontrolü olmaksızın kopyalanır/ değiştirilir veya kod birçok modüle ayrılır. Eğer biri inline işlevini sadece bir yerde değiştirirse, diğer kaynak dosyaları eski versiyonu içerebilir.

Nasıl kaçınılır:

  • Eğer inline değilse, .h dosyasında sınıf dışında işlev tanımlamayın.
  • Include guard kullanın ve tanım için tek bir yerin kontrolünü sağlayın.
  • Sabit değişkenler için constexpr veya C++17 ile inline değişkenlerini kullanın.

Zorluk Sorusu

Aynı isimde ve farklı tanımlamaya sahip static işlevler (static void foo()) farklı .cpp dosyalarında tanımlanabilir mi?

Birçok kişi static işlevlerin modüller arasında birbirini etkilemeyeceğini düşünmektedir. Cevap: evet, çünkü her biri kendi çeviri biriminde görünür (internal linkage). Ancak inline işlevler ve şablonlar için bu garanti edilir değil; bu sıkça karıştırılır.

Örnek:

// file1.cpp static void foo() { std::cout << "A"; } // file2.cpp static void foo() { std::cout << "B"; }

Bu modüllerdeki çağrılar bağımsız olacaktır.

Gerçek hataların örnekleri konunun inceliklerini bilmediğinden


Hikaye

Büyük bir projede bir geliştirici, bir kopya .h dosyasının içinde inline işlevinin gövdesini yalnızca birinde değiştirdi. Derlemeden sonra bazı davranışlar öngörülemez hale geldi: bazı modüller eski algoritma ile, bazıları ise yeni ile çalıştı. Sebep — inline işlev için ODR ihlali.



Hikaye

C++17'ye geçişte, sabit değişken birden fazla başlık dosyasında inline anahtar kelimesi kullanılmadan tanımlandı. Bağlama sırasında birçok duplicate symbol hatası ortaya çıktı. inline const değişkenini tanımlayarak düzeltildi.



Hikaye

Geç derlenmiş bir sistem .h dosyası, şablon sınıfının aynı yönteminin iki tanımını içeriyordu; bunlar farklı derlemelerde bir ifdef kontrolü ile farklılık gösteriyordu. Daha sonra uygulama, bağlı modüller arasında ABI tutarsızlığı nedeniyle dönemsel olarak çöküyordu.