2012-02-27 28 views
9

Paylaşılan kitaplığımda, yükleme zamanında belirli bir başlatma yapmam gerekiyor. Bu işlevi GCC özniteliği __attribute__ ((constructor)) ile tanımladım, çalışmaz, yani paylaşılan kitaplığımı bağlayan program yüklendiğinde çağrılmaz.paylaşılan kütüphane kurucusu çalışmıyor

İşlev adını _init() olarak değiştirirseniz, çalışır. Görünüşe göre, _init() ve _fini() işlevlerinin kullanımı şu anda not recommended.

Neden __attribute__ ((constructor)) işe yaramaz? Bu Linux 2.6.9, gcc versiyonu ile 3.4.6

Düzenleme: .bu bina için

#include <stdio.h> 

int smlib_count; 

void __attribute__ ((constructor)) setup(void) { 
    smlib_count = 100; 
    printf("smlib_count starting at %d\n", smlib_count); 
} 

void smlib_count_incr() { 
    smlib_count++; 
    smlib_count++; 
} 

int smlib_count_get() { 
    return smlib_count; 
} 

: Örneğin

, kütüphane kod aşağıdaki gibi olduğunu varsayalım .bu standart konumlarda bengüncellemek birinde olmadığından

gcc -fPIC -c smlib.c 
ld -shared -soname libsmlib.so.1 -o libsmlib.so.1.0 -lc smlib.o 
ldconfig -v -n . 
ln -sf libsmlib.so.1 libsmlib.so 

: Ben aşağıdakileri yapınve .so'yu başka bir programdan bağlayın. Kurucu aramıyor. _init() olarak değiştirirseniz, çalışır.

+0

Bu alakalıdır. Seninki nerede? Benim gibi çalışan bir tane var: void __attribute__ ((constructor)) constructor() {...} '. 'Void' ve constructor() 'dan sonra olduğunu unutmayın. –

+1

Sorumun cevabı değil, ancak paylaşımlı kütüphane kurucular genellikle * sebebiyle karışıklık main' girilir 'önce programın başlangıç ​​durumu kabiliyetlerine * Zararlı Sayılan dikkati çekiyor. Daha sonra ALSA cihazı kendisinin açılması uygulamanın engelleyen bir şekilde ALSA kütüphanesi/cihaz durumu ile munged (I sabit ama emin değilim çünkü inanıyoruz en az bir zamanda) ve en az bilinen, örneğin OpenAL'in vardır. Uygun kütüphaneler, herhangi bir küresel duruma sahip olmaktan kaçınmak için ellerinden gelenin en iyisini yapmalı ve eğer gerekli ise, ilk kütüphane çağrısında temsili başlatmayı kullanmalıdır. –

+0

@Dan Fego, Yukarıda önerdiğiniz gibi farklı yerleşimler denedim. Hala çalışmıyor. – Manohar

cevap

2

Tamam, bu konuya bir baktım ve bu durumun gerçekleştiğine benziyor, aradığınız gcc adımının (-c kullanılarak) soruna neden olması. İşte gördüğüm şey hakkındaki yorumum.

Eğer setup() ile .o olarak derleme, (bir .so olarak derleme değiliz çünkü, bu nedenle umursamıyor) gcc sadece normal fonksiyonu gibi davranır. Daha sonra, ld, herhangi bir _init() ya da ELF'nin dinamik bölümünde DT_INIT gibi herhangi bir şey görmüyor ve kurucu olmadığını varsayar.

_init() ile .o derlediğinizde, gcc da normal bir işlev olarak davranır. Aslında, bana gibi görünüyor, nesne dosyalarının isimleri kendileri hariç aynıdır! Yani, bir kez daha, ld, .o dosyasına bakar, ancak bu kez aradığını bildiği bir _init() işlev görür ve bir kurucu karar verir ve buna karşılık yeni .so içinde bir DT_INIT giriş oluşturur. Böyle derlenmesini ve tek adımda bağlama yaparsanız

Son olarak:

gcc -Wall -shared -fPIC -o libsmlib.so smlib.c 

Sonra ne olacak gcc görür ve bir paylaşılan nesne oluşturma bağlamında __attribute__ ((constructor)) anlar ve yaratmasıdır DT_INIT girişi buna göre.

Kısa versiyon: Bir adımda derlemek ve bağlantı kurmak için gcc kullanın. Gerekirse -Wl,-soname,libsmlib.so.1 gibi -soname gibi ek seçenekler için -Wl (man sayfasına bakın) kullanabilirsiniz.this link itibaren

+0

güzel ... bunu açıklıyor. Teşekkürler! – Manohar

+5

Tek adımda olmak zorunda değil. Çalışmasını sağlayan şey gcc'yi bağlantı kurmak için -shared ile değil, ld ile kullanmaktır. – Thomas

+0

Kurucuya ancak 2 adımla (.o sonra .so) sahip olmak için seçenek yok mu? CMake projeleri için gereklidir. – dashesy

2

.

"Paylaşılan kütüphaneler (gcc argümanıyla -nostartfiles '' ya da-nostdlib '' bu argümanlar kullanılırsa, yapıcı/yıkıcı rutinleri yürütülmez ile derlenmiş edilmemelidir özel olmadıkça önlemler alınır. " -nostdlib kullanıldığında

gcc/ld Elf başlığında DT_INIT bitini ayarlamak değildir. Objdump -p'yi kontrol edebilir ve her iki durumda da INIT bölümünü arayabilirsiniz. In özelliğin ((kurucu)) vaka alışkanlık o INIT bölümünü bulun. Ancak __init durumunda, paylaşılan kütüphanede INIT bölümünü bulacaksınız. fonksiyon tanımında Öznitelik dizesini nerede

İlgili konular