سؤال

في المثال التالي، يجب طباعة برنامج "فو تسمى":

// foo.c
#include <stdio.h>

__attribute__((constructor)) void foo()
{
    printf("foo called\n");
}

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

إذا يتم ترجمة مثل هذا البرنامج، وأنها تعمل:

gcc -o test main.c foo.c

ولكن، إذا جمعت foo.c إلى مكتبة ثابتة، برنامج طباعة أي شيء.

gcc -c main.c
gcc -c foo.c
as rcs foo.a foo.o
gcc -o test foo.a main.o

لماذا يحدث هذا؟

هل كانت مفيدة؟

المحلول

لا يتضمن رابط التعليمات البرمجية في foo.a في البرنامج النهائي لأن لا شيء في المراجع main.o ذلك. إذا تم إعادة كتابة main.c على النحو التالي، سيعمل البرنامج:

//main.c

void foo();

int main()
{
    void (*f)() = foo;
    return 0;
}

وبالإضافة إلى ذلك، عند ترجمة مع مكتبة ثابتة، وترتيب الحجج لدول مجلس التعاون الخليجي (أو رابط) مهم: المكتبة يجب أن يأتي بعد الكائنات التي تشير إلى أنه

gcc -o test main.o foo.a

نصائح أخرى

وكما قيل، والرموز غير مرجعية من أرشيف لا تجعل من لثنائي الإخراج، لأن رابط يتجاهل بشكل افتراضي.

لتجاوز هذا السلوك عند ربط مع مكتبة ثابتة، خيارات --whole-archive / --no-whole-archive لرابط يمكن استخدام مثل هذا:

gcc -c main.c
gcc -c foo.c
ar rcs foo.a foo.o
gcc -o test -Wl,--whole-archive foo.a -Wl,--no-whole-archive main.o

وهذا قد يؤدي إلى ثنائي المتضخمة، لأن كل حرف من foo.a ستدرج بواسطة رابط إلى الإخراج، ولكن أحيانا ما يبرره.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top