"إذا أراد العامل أن يؤدي عمله بشكل جيد، فعليه أولاً أن يشحذ أدواته." - كونفوشيوس، "مختارات كونفوشيوس. لو لينجونج"
الصفحة الأمامية > برمجة > لماذا يؤدي ربط pthread بشكل ثابت مع g++ إلى خطأ تجزئة، وكيف يمكنني حله باستخدام خيار `--whole-archive`؟

لماذا يؤدي ربط pthread بشكل ثابت مع g++ إلى خطأ تجزئة، وكيف يمكنني حله باستخدام خيار `--whole-archive`؟

تم النشر بتاريخ 2024-11-15
تصفح:826

Why does statically linking pthread with g   lead to a segmentation fault, and how can I resolve it using the `--whole-archive` option?

عندما يربط g بشكل ثابت pthread، مما يتسبب في خطأ التجزئة، لماذا؟

في الارتباط الثابت، سيتوقف الرابط عند الرمز الأول، حتى إذا كان ضعيفًا، وتوقف عن البحث عن الأقوياء. لإجباره على النظر إلى جميع الرموز (كما هو الحال مع مكتبة مرتبطة ديناميكيًا)، يدعم ld خيار --whole-archive.

سيعمل الأمر التالي:

g   -o one one.cpp -Wall -std=c  11 -O3 -static -pthread \
    -Wl,--whole-archive -lpthread -Wl,--no-whole-archive

إليك ما يحدث:

  • -pthread يعني الارتباط ضد pthread (واعتمادًا على النظام الأساسي، فهو يحدد وحدات ماكرو إضافية مثل -D_REENTRANT).
  • حتى إذا كان -pthread يعني الارتباط مقابل -lpthread، فإنك لا تزال بحاجة إلى تحديد -lpthread بشكل صريح أثناء الارتباط بشكل ثابت.
  • Wl,-- يفرض الأرشيف الكامل على الرابط تضمين كل ملف كائن في الأرشيف في الارتباط، بدلاً من البحث في الأرشيف عن ملفات الكائنات المطلوبة.
  • Wl,--no-whole-archive يوقف تأثير - خيار الأرشفة الكاملة لملفات الأرشيف اللاحقة.

فهم الرموز الضعيفة

تنسيق ملف ELF له مفهوم الرموز الضعيفة والقوية. بشكل افتراضي، تكون الرموز الموجودة في ملف الكائن قوية. أثناء الربط، يمكن للرمز القوي أن يطغى على الرمز الضعيف الذي يحمل نفس الاسم.

في حالة glibc و pthreads، يستخدمون رموزًا ضعيفة. على سبيل المثال، يتطلب POSIX أن يكون fputc آمنًا ويجب مزامنته، وهو أمر مكلف. في بيئة ذات ترابط واحد، لا تريد دفع هذه التكاليف. وبالتالي، يمكن للتطبيق تنفيذ وظائف المزامنة ككعبات فارغة، وإعلان الوظائف كرموز ضعيفة.

لاحقًا، إذا تم ربط مكتبة متعددة الخيوط (على سبيل المثال، pthread)، يصبح من الواضح أن دعم مؤشر ترابط واحد ليس المقصود. عند ربط مكتبة متعددة الخيوط، يمكن للرابط بعد ذلك استبدال بذرة بوظائف المزامنة الحقيقية (المحددة كرموز قوية ويتم تنفيذها بواسطة مكتبة الخيوط).

تطبيق هذا على البرنامج النموذجي

تحتوي مكتبة libc.a على __pthread_mutex_lock كرمز ضعيف، وتحتوي مكتبة libpthread.a عليه كرمز قوي. عند الارتباط ديناميكيًا، يستبدل الرابط الرمز الضعيف بالرمز القوي. ومع ذلك، عند الارتباط بشكل ثابت، تحتاج إلى فرض نفس الدلالات. لهذا السبب -Wl,--whole-archive -lpthread -Wl,--no-whole-archive ليس هناك حاجة إلى أرشيف كامل.

أحدث البرنامج التعليمي أكثر>

تنصل: جميع الموارد المقدمة هي جزئيًا من الإنترنت. إذا كان هناك أي انتهاك لحقوق الطبع والنشر الخاصة بك أو الحقوق والمصالح الأخرى، فيرجى توضيح الأسباب التفصيلية وتقديم دليل على حقوق الطبع والنشر أو الحقوق والمصالح ثم إرسالها إلى البريد الإلكتروني: [email protected]. سوف نتعامل مع الأمر لك في أقرب وقت ممكن.

Copyright© 2022 湘ICP备2022001581号-3