Rabu, November 06, 2019

Bagaimana Linker Menyelesaikan Simbol Global yang didefinisikan di Banyak Tempat?

Ketika melakukan kompilasi program, compiler akan mengeksport setiap simbol global menuju ke assembler apakah termasuk kategori yang kuat atau lemah, selanjutnya assembler melakukan encode informasi tersebut secara implisit dalam tabel simbol dari file object relokasi. Fungsi dan inisialisasi variabel global akan mendapatkan simbol yang kuat. Sedangkan variabel global yang tidak diinisialisasi akan mendapatkan simbol yang lemah. Untuk lebih memahami pendefinisian ini perhatikan contoh program berikut ini.


Tentukan apakah simbol berikut ini termasuk simbol yang kuat atau lemah, Unix Linker menggunakan aturan berikut ini untuk beurusan dengan banyak simbol yang didefinisikan:

Aturan satu: Multiple strong simbol dengan nama variabel sama tidak dibolehkan.

Aturan dua: Jika diberikan strong simbol dan weak simbol, maka yang dipilih adalah strong simbol.

Aturan tiga: Jika diberikan banyak weak simbol, pilih salah satu dari weak simbol apapun. Contohnya, misalnya akan berupaya untuk mengkompilasi dan menautkan dua modul bahasa C berikut ini:

/* foo1.c */
int main()
{
return 0;
}

/* bar1.c */
int main()
{
return 0;
}

Pada contoh program sebelumnya, akan dihasilkan pesan error karena strong simbol main didefinsikan lebih dari satu kali (aturan satu);

$ gcc foo1.c bar1.c
/tmp/cca015022.o: In function ‘main’:
/tmp/cca015022.o(.text+0x0): multiple definition of ‘main’
/tmp/cca015021.o(.text+0x0): first defined here

Dengan hasil yang sama, akan dihasilkan pesan error dari modul berikut karena strong simbol x didefinisikan dua kali (aturan satu);


Namun demikian, jika x tidak diinisialisasi dalam satu modul, maka linker akan memilih strong simbol yang didefinisikan pada (aturan dua) modul lainnya seperti contoh program berikut ini:


Saat waktu running program, fungsi f() mengubah nilai dari x yang awalnya 15213 menjadi 15212, yang mungkin saja tidak diterima oleh author dari fungsi main. catatan, bahwa linker umumnya tidak memberikan indikasi bahwa telah mendeteksi definisi ganda dari x.

$ gcc -o gfg foo3.c bar3.c
$ ./gfg
x = 15212

Hal serupa juga dapat terjadi jika terdapat dua definisi weak dari x (aturan 3).


Penerapan aturan dua dan aturan tiga dapat mengakibatkan bug runtime yang berbahaya yang tidak inconferehensif bagi para programmer, khususnya jika terjadi pendefinisikan duplikasi simbol pada tipe yang berbeda Contoh; x didefinisikan sebagai int pada modul satu dan juga didefinisikan pada modul yang lainnya.

Output:
$ gcc a.c b.c -o geeksforgeeks
$ ./geeksforgeeks
x = 0x0 y = 0x80000000

Program yang telah dibuat tersebut telah menghasilkan bug, khususnya karena bug tersebut sulit dideteksi, karena tidak ada pesan warning dari sistem kompilasi, dan juga bug tersebut tetap dapat muncul pada bagian program lainnya, jauh dari tempat kemunculan awal dari bug tersebut. Pada program dengan skala yang lebih luas jenis bug yang telah diciptakan seperti ini akan jauh lebih sulit lagi untuk dideteksi, khususnya karena banyak programmer tidak antisipasi terhadap bagaimana linker bekerja. Tanpa ragu, seorang programmer memanggil linker dengan flag seperti gcc -fno-common flag, yang dapat men-trigger error dalam multi definisi simbol yang global.





Related Posts

Bagaimana Linker Menyelesaikan Simbol Global yang didefinisikan di Banyak Tempat?
Oleh

"semoga yang memberikan komentar diberikan berkah kebaikan dari Allah, dijauhkan dari kejahatan, dan diberikan pahala ilmu dan amal jariyah dari sepenggal kata yang ia tinggalkan amiin :) "