Thread overview
C++'da Gizli Veriye Ulaşımı Kesin Olarak Engellemek
Dec 15, 2017
İbrahim
Dec 15, 2017
cos00kun
December 15, 2017

Selamün Aleyküm;

C++'da şöyle bir sınıf olduğunu varsayalım:

class Example
{
private:
 int _n;
} cls;

_n değişkenine erişemiyoruz, lakin ufak tefek sihirbazlıklarla bu gizli veriye erişip değerini değiştirebiliyoruz:

*((int*)(&cls)) = 7;

Yani aslında bir şekilde illaki private anahtar sözcüğünü devredışı bırakabiliyoruz. O zaman da private'ın pek anlamı kalmamış oluyor gibi :).
Peki gizli olan sınıf verisini dışarıdan erişimini kesin bir şekilde engellemenin yolu var mıdır? Bu durumun D dilindeki durumu nedir?
Teşekkürler.

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

December 15, 2017

private: ile yazan bölümlere erişilebildiğini ilk defa duydum ve sayenizde öğrendim :-)
Aslında ben şöyle düşünüyorum;
Programlama dillerine bu özellik eklenirken amaç sanki Private ile erişimsizlik sağlamak yerine, yapılacak hatalardan korumakmış gibi geliyor bana.

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

December 15, 2017

Bunun engellemenin kesin bir yolu yok. Ben bu işin biraz fazla ileri gittiğini düşünmeye de başladım. Sistem programcıları önünde sonunda bir şeylere erişmek zorunda kalabiliyorlar.

Evet, dediğin gibi yapılabildiği gibi, kütüphane içindeki mangled isimleriyle de erişilebiliyor.

Örneğin, core.thread'in kendi işi için tanımlamış olduğu 'sm_tbeg' değişkenine şöyle erişebiliyoruz (sm_tbeg, "static member, thread begin"in kısaltması; çöp toplayıcının haberi olduğu iş parçacıklarının listesinin başı):

import core.thread;

void main() {
   // Derlenemez çünkü core.thread.sm_tbeg private
   static assert(!__traits(compiles, core.thread.sm_tbeg));
}

Yapabildiğimiz bir şey, sm_tbeg'in kütüphane içindeki ismini bulmak. Örneğin, linux ortamında:
'
$ nm deneme | grep sm_tbeg
000000000066b668 B _D4core6thread6Thread7sm_tbegCQBcQBaQw
'
Şimdi o ismi doğrudan kullanabiliriz çünkü private gibi kavramlar derleme aşamasından sonra ortadan kalkar. Programın bağlandığı şey, sembolün kütüphanedeki ismidir:

import std.stdio;
import core.thread;

// Bu, sm_tbeg'in bizim dışımızda tanımlı olduğunu (çünkü extern) ve biz burada
// sm_tbeg diyeceğimiz halde, kütüphane içinde o garip isme sahip olduğunu
// söylüyor.
pragma(mangle, "_D4core6thread6Thread7sm_tbegCQBcQBaQw")
extern __gshared Thread sm_tbeg;

void main() {
   // İşte kullanabiliyoruz (spawn, new Thread, vs. ile başka iş parçacığı
   // başlatırsanız birden fazla yazdırıldığını göreceksiniz):
   foreach (t; sm_tbeg) {
       writeln(t);
   }
}

nm yöntemini kullanmak yerine, core.demangle'ı doğrudan kullanmak çok daha kolay ve derleyici sürümü değiştiğinde bile nm'i bir daha çağırmak gerekmeden doğru çalışır:

import std.stdio;
import core.thread;
import core.demangle;

pragma(mangle, mangle!(core.thread.Thread)("core.thread.Thread.sm_tbeg"))
extern __gshared Thread sm_tbeg;

void main() {
   foreach (t; sm_tbeg) {
       writeln(t);
   }
}

Ben artık private, protected, vs.'nin yarardan çok zarar getirdiklerini düşünüyorum. Sonuçta, hepimiz türleri belgelerine göre, yani tasarlandıkları gibi kullanıyoruz. Eğer private üyeyle oynarsak başımızın belaya girebileceğini biliyoruz. E, tamam: bile bile yapıyorsak sonuçlarına da katlanırız zaten. :)

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

December 15, 2017

Evet, asıl amaç hem programcı hatalarından korunmak hem de tasarımı ileride serbestçe değiştirebilmek. private olan üyelerin yalnızca bu modül tarafından kullanıldığını biliyorsak, kendi gerçekleştirmemizi başka programcıların kodlarını bozmadan serbestçe değiştirebiliriz.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]