Forum: Diğer Konular RSS
C++/D Linker Nasıl Bir Mantıkla Çalışıyor?
İbrahim #1
Üye Eki 2015 tarihinden beri · 156 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Konu adı: C++/D Linker Nasıl Bir Mantıkla Çalışıyor?
Selamün Aleyküm.

Bundan bir önceki "İnşa Araçları" adlı konumda Ali Hocam g++ a.cpp b.cpp -o app şeklinde derlemem gerektiğini söylediniz, yoksa linker sorunu olacağını söylediniz. Şimdiki konum işte bu konuda. Şöyle bir örnek var: http://www.tutorialspoint.com/makefile/why_makefile.htm. Buradaki örneği g++ hello.cpp -o hello olarak derlemeye çalıştım ve hata aldım. Sonra bir tane de kendim örnek yaptım şu şekilde:
// functions.h
int factorial(int n);
int max(int x, int y);
 
// functions.cpp
#include <functions.h>
 
int factorial(int n)
{
    return (n > 1) ? n * factorial(n - 1) : 1;
}
 
int max(int x, int y)
{
    return (x > y) ? x : y;
}
 
// main.cpp
#include <iostream>
 
#include "functions.h"
 
using namespace std;
 
int main()
{
    cout << "Factorial of 5 is " << factorial(5);
    cout << endl;
    cout << "Max(5, 7) = " << max(5, 7) << endl;
 
    return 0;
}
Terminalde şu şekilde: g++ main.cpp -o main derlemeye çalıştım fakat hata verdi. Dediğim gibi hatanın linker'dan kaynaklandığını biliyorum. Fakat bu örneği mesela QtCreator gibi bir ide'de yazınca çalıştır diyorsun ve çalışıyor fakat bir editörde yazında terminalden çalışmıyor. Acaba bu linker functions.cpp'de fonksiyon kodları olduğu halde main'de sadece functions.h yi çağırınca nasıl birbirine bağlıyor? Terminalde neden g++ main.cpp -o main yazınca çalışmıyor da g++ main.cpp functions.cpp -o main yazınca çalışıyor? Tüm cpp dosyalarını derlemeyle linker'ın arasında nasıl bir bağlantı var? Çalıştığım kitapta bunu şu an görmedim, sanırım ilerki sayfalarda bahsedecek ama şu an merak ettim.
Ali Hocam cevap verirseniz sevinirim, nasıl olsa sitede ikimiz varız genelde :)
Teşekkürler!
acehreli (Moderatör) #2
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Bağlayıcı (linker) ve onun ikiz kardeşi yükleyici (loader) işletim sistemi ile ilgili konulardır. Temelde çok basit bir kavramdır:

Derlenmiş bir program parçası (.o dosyası), bir kavramı ismiyle anarak bir işlem yapar: "g_değişken adlı değişkenin değeri bir arttırılıyor" gibi. Olasılıkla, g_değişken adlı değişken başka bir .o (veya kütüphane) dosyasındadır. Bağlayıcının görevi, bu iki .o dosyasını belleğe yerleştirmek ve ismiyle g_değişken diye anılan değişkenin bu yerleşim sonrasında tam olarak nerede olduğunu görmek ve yukarıdaki ifadeyi "0x1234 adresindeki değişkenin değeri bir arttırılıyor" diye değiştirmektir.

Aynısı işlevler için de geçerlidir: Program parçaları ve kütüphaneler belleğe okunduktan sonra onlar içindeki "foo()'yu çağırıyoruz" gibi ifadeleri "0x5678 adresindeki kodu işletiyoruz" gibi ifadelerle değiştirir.

Gerçekten, temelde bundan başka bir şey değil. Ancak, her olayda olduğu gibi, bağlayıcıların binbir ayrıntısı var: Derlenmiş dosyalar ve kütüphaneler için farklı düzenler (ELF, vs.), farklı işletim sistemleri, vs.

İbrahim:
g++ hello.cpp -o hello olarak derlemeye çalıştım ve hata aldım.

Çünkü derlenmiş kod içinde örneğin "foo()'yu çağır" gibi bir bilgi var ama bağlayıcının elinde bulunan hiçbir program parçasında foo()'nun tanımı yok. Hiçbir şey yapamaz.

g++ main.cpp -o main

Aynı neden: main'in çağırdığı işlevler programı oluştururken kullanılmamış. main.cpp'nin functions.h'yi eklemiş olması hiç yeterli değil çünkü onun bildirdiği işlevlerinin hangi kaynak dosyalarda olduklarını bağlayıcıya söylemiyoruz.

QtCreator gibi bir ide'de yazınca çalıştır diyorsun ve çalışıyor

Çünkü o perde arkasında bütün dosyaları kullanıyor: g++ main.cpp functions.cpp -o main

main'de sadece functions.h yi çağırınca

Hassas konuşmakta yarar var: :) main functions.h'yi olduğu gibi ekliyor ve örneğin factorial() diye bir işlevin varlığını öğreniyor. Böylece, factorial(5) yapıldığında derleme hatası oluşmuyor. Ancak, derlenen kodda yalnızca şu bilgi var: "burada factorial'ı 5 değeri ile çağırıyoruz." O kadarı derleme için yeterli ama programın çalışması sırasında onun factorial'ın gerçek bellek adresine gidecek biçimde değiştirilmesi (bağlanması) gerek.

Terminalde neden g++ main.cpp -o main yazınca çalışmıyor

Tekrarlamak pahasına: Yalnızca main.cpp programı oluşturmak için yeterli değil.

da g++ main.cpp functions.cpp -o main yazınca çalışıyor?

Şimdi bütün tanımlar var.

Çalıştığım kitapta

Hangi kitap?

Ali
İbrahim #3
Üye Eki 2015 tarihinden beri · 156 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Aynı neden: main'in çağırdığı işlevler programı oluştururken kullanılmamış. main.cpp'nin functions.h'yi eklemiş olması hiç yeterli değil çünkü onun bildirdiği işlevlerinin hangi kaynak dosyalarda olduklarını bağlayıcıya söylemiyoruz.
Anladığım kadarıyla tüm cpp dosyalarını derlemeyle oluşan .o dosyasından asıl olarak verilere ulaşılıyor, cpp'lerin bir kısmını derlemezsek bağlayıcı (linker) mesela fonksiyonun kodlarını .o dosyası oluşmadan bulamıyor ve hata veriyor. Doğru anlamışımdır umarım.

Hangi kitap?
Bu kitap: http://www.kitapyurdu.com/kitap/nesne-yonelimli-c-programl… sizce iyi midir bu kitap?
acehreli (Moderatör) #4
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
İbrahim:
tüm cpp dosyalarını derlemeyle oluşan .o dosyasından

Her .cpp'ye karşılık bir .o oluşuyor; birleştirilerek tek .o oluşmuyor.

cpp'lerin bir kısmını derlemezsek bağlayıcı (linker) mesela fonksiyonun kodlarını .o dosyası oluşmadan bulamıyor

Evet. Ama çok mantıklı, değil mi? Bağlayıcı olmayan şeylerle program oluşturamıyor.


ACCU iyi bulmamış:

  http://accu.org/index.php?module=bookreviews&func=sear…

Ali
İbrahim #5
Üye Eki 2015 tarihinden beri · 156 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Peki Qt bildiğimiz gibi uygulamaları statik derlemeyi yasal kabul etmiyor. Acaba bu .o dosyalarını da beraberinde vermemizi mi istiyor? Statik derleme tam olarak bu .o dosyalarını ve dll gibi dosyaları hep birlikte mi derliyor?

ACCU'ya baktım ve anladığım kadarıyla 1-2 anlatım hatasından bahsetmiş, İnşallah bana yanlış öğretmiyordur kitap :) .
acehreli (Moderatör) #6
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
İbrahim:
Qt bildiğimiz gibi uygulamaları statik derlemeyi yasal kabul etmiyor.

Bundan haberim yok. Acaba eskiden yalnızca dinamik kütüphane mi veriyorlardı?

Statik derleme tam olarak bu .o dosyalarını ve dll gibi dosyaları hep birlikte mi derliyor?

Statik bağlama, bütün işlev tanımlarının programın içine gömülmesidir. Örneğin, çağrılan foo() falanca.a kütüphanesindedir; bağlayıcı foo()'nun tanımını (doğrusu, bütün falanca.a kütüphanesini) programa dahil eder. Program büyük olur ama tanım tam da istenen yerde bulunur.

Sakıncalar: falanca.a kütüphanesini kullanan her program onun bir kopyasını içerir. Programlar büyük olduklarından gerçek belleğe sığma şansları azalır; sistem yavaşlar. (Yararları da var.)

Dinamik bağlamada ise foo()'nun tanımı veya falanca.so programa dahil edilmez. Ancak, foo()'nun hangi kütüphanede bulunduğu programa yazılır. Program başlayınca falanca.so dosyası açılır ve programın belleğinin bir parçasına yazılır.

Sakınca: Programlar daha geç başlarlar çünkü falanca.so'nun bulunması ve belleğe okunması, işlev adreslerinin buna uygun olarak ayarlanması, vs. gerekir. Ama, işletim sistemi her program için ayrı falanca.so açmaz; hepsine aynı gerçek bellek bölgesinden hizmet eder. Böylece programlar bellekte topluca daha az yer kaplarlar.

Ali
Doğrulama Kodu: VeriCode Lütfen resimde gördüğünüz doğrulama kodunu girin:
İfadeler: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O
Özel Karakterler:
Bağlı değilsiniz. · Şifremi unuttum · ÜYELİK
This board is powered by the Unclassified NewsBoard software, 20100516-dev, © 2003-10 by Yves Goergen
Şu an: 2017-11-18, 09:22:36 (UTC -08:00)