28 Aralık 2024
Çerçevemiz, CodePorting.Translator Cs2Cpp, .NET platformu için geliştirilmiş kütüphanelerin C++'ta yayınlanmasını sağlar. Bu makalede, bu iki dilin bellek modellerini nasıl uzlaştırdığımızı ve çevrilen kodun yönetilmeyen bir ortamda düzgün çalışmasını nasıl sağladığımızı tartışacağız.
Kullandığımız akıllı işaretçiler hakkında bilgi edinecek ve onlar için neden kendi uygulamalarımızı geliştirmemiz gerektiğini öğreneceksiniz. Ayrıca, nesne ömrü yönetimi perspektifinden C# kodunu taşımak için hazırlık sürecini, karşılaştığımız bazı zorlukları ve çalışmalarımızda kullanmamız gereken özel tanı yöntemlerini ele alacağız.
C# kodu, yönetilen bir ortamda çöp topla ile çalıştırılır. Çeviri amaçları doğrultusunda, bu öncelikle bir C# programcısının, bir C++ geliştiricisinden farklı olarak, artık kullanılmayan tahsis edilmiş yığın belleğini sisteme geri vermek zorunda kalmaması anlamına gelir. Bu, CLR ortamının bir bileşeni olan çöp toplayıcı (GC) tarafından gerçekleştirilir. GC, programda hangi nesnelerin hala kullanıldığını periyodik olarak kontrol eder ve artık aktif referansları olmayan nesneleri temizler.
Aktif bir referans şu şekilde kabul edilir:
Çöp toplayıcı algoritması genellikle, yığın ve statik alanlarda bulunan referanslardan başlayarak nesne grafiğini dolaşmak ve önceki aşamada ulaşılamayan her şeyi silmek olarak tanımlanır. GC işlemi sırasında referans grafiğini geçersiz hale getirmekten korunmak için, bir dünyayı durdur mekanizması uygulanır. Bu açıklama basitleştirilmiş olabilir, ancak amaçlarımız için yeterlidir.
Akıllı işaretçilerden farklı olarak, çöp toplama yaklaşımı çapraz veya döngüsel referans sorunundan muaftır. İki nesne birbirine, muhtemelen birkaç ara nesne aracılığıyla referans veriyorsa, GC'nin, izolasyon adası olarak bilinen grubun tamamında artık aktif referans bulunmadığında bunları silmesini engellemez. Sonuç olarak, C# programcılarının nesneleri herhangi bir zamanda ve herhangi bir kombinasyonda birbirine bağlama konusunda hiçbir önyargısı yoktur.
C#'taki veri türleri referans ve değer türlerine ayrılır. Değer türlerinin örnekleri her zaman yığında, statik bellekte veya doğrudan yapıların ve nesnelerin alanlarında bulunur. Buna karşılık, referans türlerinin örnekleri her zaman yığın üzerinde oluşturulur ve yığında, statik bellekte ve alanlarda yalnızca referansları (adresleri) saklanır. Değer türleri yapılar, ilkel aritmetik değerler ve referansları içerir. Referans türleri ise sınıflar ve tarihsel olarak, delegeleri içerir. Bu kuralın tek istisnası, bir yapının veya başka bir değer türünün belirli bir bağlamda kullanılmak üzere yığına kopyalandığı kutulama durumlarıdır.
Nesnenin imha edilme anı tanımlanmamıştır—dil, nesneye yapılan son aktif referansın kaldırılmasından önce gerçekleşmeyeceğini garanti eder. Dönüştürülen kodda, nesne son aktif referansın kaldırılmasının hemen ardından yok edilirse, bu programın çalışmasını aksatmaz.
Diğer önemli bir nokta, C#'ta genel türler ve yöntemler desteği ile ilgilidir. C#, genel türlerin bir kez yazılmasını ve ardından bunların hem referans hem de değer türü parametreleriyle kullanılmasını sağlar. Daha sonra gösterileceği gibi, bu nokta önemli olduğunu kanıtlıyor.
C# türlerini C++ türlerine nasıl eşlediğimiz hakkında birkaç kelime. CodePorting.Translator Cs2Cpp çerçevesi uygulamalardan ziyade kütüphanelerin taşınması için tasarlandığından, bizim için önemli bir gereklilik, orijinal .NET projesinin API'sini mümkün olduğunca doğru bir şekilde yeniden üretmektir. Bu nedenle, C# sınıflarını, arayüzlerini ve yapıları karşılık gelen temel türleri miras alan C++ sınıflarına dönüştürüyoruz.
Örneğin, aşağıdaki kodu düşünün:
interface I1 {}
interface I2 {}
interface I3 : I2 {}
class A {}
class B : A, I1 {}
class C : B, I2 {}
class D : C, I3 {}
class Generic<T> { public T value; }
struct S {}
Bu şekilde çevrilecektir:
class I1 : public virtual System::Object {};
class I2 : public virtual System::Object {};
class I3 : public virtual I2 {};
class A : public virtual System::Object {};
class B : public A, public virtual I1 {};
class C : public B, public virtual I2 {};
class D : public C, public virtual I3 {};
template <typename T> class Generic { public: T value; };
class S : public System::Object {};
System::Object
sınıfı, dönüştürülen projeye dışsal olarak çeviri destek kütüphanesinde ilan edilmiş bir sistem sınıfıdır. Sınıflar ve arayüzler, elmas problemi 'ni önlemek için sanal olarak miras alınır. C++ koduna dönüştürülen yapılarda System::Object
miras alınırken, C#'ta bu miras System.ValueType
üzerinden alınır, ancak optimizasyon amacıyla bu ek miras kaldırılmıştır. Genel türler ve yöntemler, sırasıyla şablon sınıflarına ve yöntemlerine dönüştürülür.
Dönüştürülen türlerin örnekleri, C# tarafından sağlanan aynı garantilere uymalıdır. Sınıf örnekleri yığında oluşturulmalı ve ömürleri aktif referansların ömrü ile belirlenmelidir. Yapı örnekleri, kutulama durumları hariç, yığında oluşturulmalıdır. Delege, bu makalenin kapsamı dışında kalan özel ve nispeten basit bir durumdur.
C#'taki bellek yönetim modelinin C++'a kod dönüştürme sürecini nasıl etkilediğini ele aldık. Makalenin bir sonraki bölümünde, yığında tahsis edilen nesnelerin ömrünü yönetme yöntemine nasıl karar verildiğini ve bu yaklaşımın nasıl uygulandığını tartışacağız.