লাইব্রেরিগুলিতে যে আদেশটি লিঙ্ক করা হয়েছে তা কেন কখনও কখনও জিসিসিতে ত্রুটি সৃষ্টি করে?


449

লাইব্রেরিগুলিতে যে আদেশটি লিঙ্ক করা হয়েছে তা কেন কখনও কখনও জিসিসিতে ত্রুটি সৃষ্টি করে?


আরও দেখুন এখন stackoverflow.com/questions/7826448/... - TLDR gccআরো-কঠোর আচরণ (অপেক্ষাকৃত) সম্প্রতি পরিবর্তন করা হয়েছে।
ট্রিপলি

উত্তর:


557

(আরও বিস্তৃত পাঠ্য পেতে এই উত্তরের ইতিহাস দেখুন, তবে আমি এখন মনে করি পাঠকের পক্ষে আসল কমান্ড লাইনগুলি দেখতে আরও সহজ)।


সাধারণ ফাইলগুলি নীচের সমস্ত কমান্ড দ্বারা ভাগ করা

$ cat a.cpp
extern int a;
int main() {
  return a;
}

$ cat b.cpp
extern int b;
int a = b;

$ cat d.cpp
int b;

স্থির গ্রন্থাগারগুলির সাথে সংযোগ স্থাপন

$ g++ -c b.cpp -o b.o
$ ar cr libb.a b.o
$ g++ -c d.cpp -o d.o
$ ar cr libd.a d.o

$ g++ -L. -ld -lb a.cpp # wrong order
$ g++ -L. -lb -ld a.cpp # wrong order
$ g++ a.cpp -L. -ld -lb # wrong order
$ g++ a.cpp -L. -lb -ld # right order

লিঙ্কারটি বাম থেকে ডানে অনুসন্ধান করে এবং অমীমাংসিত প্রতীকগুলি যেমন যায় তেমন নোট করে। যদি কোনও লাইব্রেরি প্রতীকটি সমাধান করে তবে প্রতীকটি সমাধান করতে that লাইব্রেরির অবজেক্ট ফাইলগুলি লাগে (এক্ষেত্রে libb.a এর বাইরে)।

একে অপরের বিপরীতে স্থির গ্রন্থাগারগুলির নির্ভরতা একই কাজ করে - যে লাইব্রেরিটির জন্য চিহ্নগুলির প্রয়োজন তা অবশ্যই প্রথমে, তারপরে পাঠাগারটি প্রতীককে সমাধান করে।

যদি একটি স্ট্যাটিক লাইব্রেরি অন্য লাইব্রেরির উপর নির্ভর করে তবে অন্য গ্রন্থাগারটি আবার পূর্বের গ্রন্থাগারের উপর নির্ভর করে, সেখানে একটি চক্র রয়েছে। আপনি এটির cyclically নির্ভরশীল লাইব্রেরি পরিক্ষেপ এই সমাধান করতে পারেন -(এবং -)যেমন -( -la -lb -)(আপনি যেমন ডান বন্ধনী, অব্যাহতি প্রয়োজন হতে পারে -\(এবং -\))। সাইক্লিং নির্ভরতাগুলি সমাধান করা হয়েছে তা নিশ্চিত করার জন্য লিঙ্কার তারপরে এই সংযুক্ত লিবটি একাধিকবার অনুসন্ধান করে। অন্যথা, আপনি লাইব্রেরি একাধিক বার, তাই প্রতিটি পরস্পর আগে নির্দিষ্ট করতে পারেন: -la -lb -la

ডায়নামিক লাইব্রেরিতে লিঙ্ক করা হচ্ছে

$ export LD_LIBRARY_PATH=. # not needed if libs go to /usr/lib etc
$ g++ -fpic -shared d.cpp -o libd.so
$ g++ -fpic -shared b.cpp -L. -ld -o libb.so # specifies its dependency!

$ g++ -L. -lb a.cpp # wrong order (works on some distributions)
$ g++ -Wl,--as-needed -L. -lb a.cpp # wrong order
$ g++ -Wl,--as-needed a.cpp -L. -lb # right order

এটি এখানে একই - লাইব্রেরিগুলিকে অবশ্যই প্রোগ্রামটির অবজেক্ট ফাইলগুলি অনুসরণ করতে হবে। স্ট্যাটিক লাইব্রেরির তুলনায় এখানে পার্থক্য হ'ল আপনার একে অপরের বিরুদ্ধে লাইব্রেরিগুলির নির্ভরতা সম্পর্কে চিন্তা করার দরকার নেই, কারণ গতিশীল লাইব্রেরিগুলি তাদের নির্ভরতাগুলি নিজেরাই সাজিয়ে তোলে

কিছু সাম্প্রতিক বিতরণগুলি স্পষ্টতই --as-neededলিঙ্কার পতাকা ব্যবহারের জন্য ডিফল্ট , যা প্রবর্তন করে যে প্রোগ্রামটির অবজেক্ট ফাইলগুলি গতিশীল লাইব্রেরির আগে উপস্থিত হয়। যদি সেই পতাকাটি পাস হয়ে যায় তবে লিঙ্কারটি এমন লাইব্রেরিগুলিতে লিঙ্ক করবে না যেগুলি কার্যনির্বাহী দ্বারা প্রয়োজনীয় নয় (এবং এটি এটি বাম থেকে ডানে সনাক্ত করে)। আমার সাম্প্রতিক আর্চলিনাক্স বিতরণটি এই পতাকাটি ডিফল্টরূপে ব্যবহার করে না, সুতরাং এটি সঠিক ক্রমটি অনুসরণ না করে ত্রুটি দেয় নি didn't

প্রাক্তনটি তৈরি করার সময় এর b.soবিরুদ্ধে নির্ভরতা বাদ দেওয়া সঠিক নয় d.so। তখন লিঙ্ক করার সময় আপনার লাইব্রেরি নির্দিষ্ট করতে হবে a, তবে aসত্যিকারের পূর্ণসংখ্যার প্রয়োজন নেই b, সুতরাং এটির bনিজস্ব নির্ভরতা সম্পর্কে যত্ন নেওয়া উচিত নয় ।

এর জন্য নির্ভরতাগুলি নির্দিষ্ট করে মিস করতে পারলে এর প্রভাবগুলির উদাহরণ libb.so

$ export LD_LIBRARY_PATH=. # not needed if libs go to /usr/lib etc
$ g++ -fpic -shared d.cpp -o libd.so
$ g++ -fpic -shared b.cpp -o libb.so # wrong (but links)

$ g++ -L. -lb a.cpp # wrong, as above
$ g++ -Wl,--as-needed -L. -lb a.cpp # wrong, as above
$ g++ a.cpp -L. -lb # wrong, missing libd.so
$ g++ a.cpp -L. -ld -lb # wrong order (works on some distributions)
$ g++ -Wl,--as-needed a.cpp -L. -ld -lb # wrong order (like static libs)
$ g++ -Wl,--as-needed a.cpp -L. -lb -ld # "right"

আপনি যদি এখন বাইনারিটির কী নির্ভরশীলতাগুলি খতিয়ে দেখেন তবে আপনি নোট করুন যে বাইনারি নিজেই নির্ভর করে libd, ঠিক libbযেমনটি করা উচিত নয়। বাইনারিটি যদি libbআবার অন্য লাইব্রেরির উপর নির্ভর করে তবে এটি পুনরায় সংযুক্ত করা দরকার, যদি আপনি এটি এভাবে করেন। এবং যদি রানটাইম libbব্যবহার করে অন্য কেউ লোড করে dlopen(ডায়ামিকভাবে প্লাগইন লোড করার কথা ভাবেন), কলটিও ব্যর্থ হবে। সুতরাং "right"সত্যিই wrongপাশাপাশি হওয়া উচিত ।


10
সমস্ত চিহ্নগুলি সমাধান না হওয়া পর্যন্ত পুনরাবৃত্তি করুন, হ - আপনি ভাবেন যে তারা কোনও টপোলজিকাল বাছাই করতে পারে। LLVM এর নিজস্ব 78 টি স্ট্যাটিক লাইব্রেরি রয়েছে, কে-কী-কী নির্ভরতাগুলির সাথে। সত্য এটির একটি সংকলন / লিঙ্ক বিকল্পগুলি বের করার জন্যও একটি স্ক্রিপ্ট রয়েছে - তবে আপনি এটি সমস্ত পরিস্থিতিতে ব্যবহার করতে পারবেন না।
স্টিভ 314

6
@Steve যে প্রোগ্রাম কি lorder+ + tsortনা। তবে কখনও কখনও কোনও অর্ডার নেই, যদি আপনার চক্রীয় রেফারেন্স থাকে। তারপরে আপনার সবকিছু সমাধান না হওয়া অবধি লাইব্রেরি তালিকার মধ্যে দিয়ে আপনাকে চক্রটি চালিয়ে যেতে হবে।
জোহানেস স্কাউব -

10
@ জোহানেস - সর্বাধিক দৃ strongly়ভাবে সংযুক্ত উপাদানগুলি নির্ধারণ করুন (যেমন টারজানস অ্যালগরিদম) তারপরে টপোলজিকভাবে উপাদানগুলির (সহজাতভাবে ন-সাইক্লিক) ডিগ্রাফকে বাছাই করুন। প্রতিটি উপাদানকে একটি লাইব্রেরি হিসাবে বিবেচনা করা যেতে পারে - যদি উপাদান থেকে কোনও একটি গ্রন্থাগার প্রয়োজন হয়, নির্ভরতা চক্র (গুলি) that উপাদানটির সমস্ত লাইব্রেরিগুলির প্রয়োজনীয়তার কারণ ঘটায়। সুতরাং না, সমস্ত সমস্যার সমাধান করার জন্য সমস্ত লাইব্রেরিগুলিতে সত্যই চক্রের দরকার নেই এবং বিশ্রী কমান্ড-লাইন বিকল্পের প্রয়োজন নেই - দুটি সুপরিচিত অ্যালগরিদম ব্যবহার করে একটি পদ্ধতি সমস্ত ক্ষেত্রে সঠিকভাবে পরিচালনা করতে পারে।
স্টিভ 314

4
আমি এই দুর্দান্ত উত্তরের একটি গুরুত্বপূর্ণ বিবরণ যোগ করতে চাই: "- (সংরক্ষণাগার -)" বা "-" -স্টার্ট-গ্রুপ সংরক্ষণাগার --end-গ্রুপ "ব্যবহার প্রতিটি সময় থেকেই বিজ্ঞপ্তি নির্ভরতা সমাধানের একমাত্র নিশ্চিত অগ্নি উপায় Using লিঙ্কার একটি সংরক্ষণাগারটিতে যান, এটি কেবলমাত্র অবৈধ ফাইলগুলিকে টেনে নিয়ে যায় (এবং এর অমীমাংসিত চিহ্নগুলি নিবন্ধভুক্ত করে) যা বর্তমানে অমীমাংসিত চিহ্নগুলিকে সমাধান করে । এর কারণে, নির্ভরতা গ্রাফের সাথে সংযুক্ত উপাদানগুলি পুনরাবৃত্তি করতে সিএমকের অ্যালগরিদম মাঝে মধ্যে ব্যর্থ হতে পারে। ( আরও বিস্তারিত জানার জন্য
ল্যাকারগুলিতে

3
আপনার উত্তরটি আমাকে আমার লিঙ্কযুক্ত ত্রুটিগুলি সমাধান করতে সহায়তা করেছে এবং আপনি সমস্যার মধ্যে পড়ে এড়াতে কীভাবে আপনি খুব স্পষ্টভাবে ব্যাখ্যা করেছেন, তবে কেন আপনার কোনও ধারণা আছে যে এটি এইভাবে কাজ করার জন্য ডিজাইন করা হয়েছিল?
আন্তন ড্যানিয়েকো

102

জিএনইউ এলডি লিঙ্কার একটি তথাকথিত স্মার্ট লিঙ্কার। এটি পূর্ববর্তী স্ট্যাটিক লাইব্রেরি দ্বারা ব্যবহৃত ফাংশনগুলি ট্র্যাক করে রাখবে, এর অনুসন্ধান সারণী থেকে ব্যবহৃত হয় না এমন ফাংশন স্থায়ীভাবে টস করে দিবে। ফলাফলটি হ'ল যদি আপনি খুব তাড়াতাড়ি একটি স্ট্যাটিক লাইব্রেরি লিঙ্ক করেন, তবে সেই লাইব্রেরির ফাংশনগুলি লিংক লাইনে পরে স্থির লাইব্রেরিতে আর উপলভ্য হবে না।

আদর্শ ইউনিক্স লিঙ্কার বাম থেকে ডানে কাজ করে, তাই আপনার সমস্ত নির্ভরযোগ্য লাইব্রেরি বামদিকে রাখুন এবং যেগুলি লিঙ্ক লাইনের ডানদিকে সেই নির্ভরতাগুলি সন্তুষ্ট করে। আপনি দেখতে পাবেন যে কিছু গ্রন্থাগার অন্যের উপর নির্ভর করে যখন একই সময়ে অন্যান্য গ্রন্থাগারগুলি সেগুলির উপর নির্ভর করে। এটি এখানে জটিল হয়ে ওঠে। যখন বিজ্ঞপ্তি রেফারেন্স আসে, আপনার কোড ঠিক করুন!


2
এটি কি কেবল gnu ld / gcc সহ? নাকি লিকারগুলির সাথে এটি সাধারণ কিছু?
মাইক

2
দৃশ্যত আরও ইউনিক্স সংকলকগুলির একই সমস্যা রয়েছে similar এমএসভিসি পুরোপুরি এই সমস্যাগুলি থেকে মুক্ত নয়, তবে তারা এটিকে খারাপ বলে মনে হয় না।
এমএসএলটাররা

4
এমএস ডেভেল সরঞ্জামগুলি এই বিষয়গুলি ততটা দেখানোর প্রবণতা রাখে না কারণ আপনি যদি একটি অল-এমএস সরঞ্জাম চেন ব্যবহার করেন তবে এটি লিঙ্কার অর্ডারটি সঠিকভাবে সেট আপ করা শেষ হবে এবং আপনি কখনই সমস্যাটি লক্ষ্য করবেন না।
মাইকেল কোহেন

16
এমএসভিসি লিঙ্কার এই ইস্যুতে কম সংবেদনশীল কারণ এটি একটি অনর্থিত চিহ্নের জন্য সমস্ত লাইব্রেরি অনুসন্ধান করবে। লাইব্রেরী অর্ডার এখনও প্রভাবিত করতে পারে যা যদি একটির বেশি গ্রন্থাগার প্রতীক আছে প্রতীক সমাধান পায়। এমএসডিএন থেকে: "লাইব্রেরিগুলিকে কমান্ড লাইন ক্রমেও অনুসন্ধান করা হয়, নিম্নোক্ত সতর্কতার সাথে: লাইব্রেরি থেকে কোনও অবজেক্ট ফাইল আনার সময় সমাধান না হওয়া প্রতীকগুলি প্রথমে সেই লাইব্রেরিতে অনুসন্ধান করা হয় এবং তারপরে কমান্ড লাইন থেকে নিম্নলিখিত লাইব্রেরি এবং / ডিফল্টলিব (ডিফল্ট লাইব্রেরি নির্দিষ্ট করুন) নির্দেশাবলী এবং তারপরে কমান্ড লাইনের শুরুতে যে কোনও লাইব্রেরিতে "
মাইকেল বার বার

4
"... স্মার্ট লিঙ্কার ..." - আমি বিশ্বাস করি এটি "স্মার্ট লিঙ্কার" নয়, "একক পাস" লিংক হিসাবে শ্রেণিবদ্ধ করা হয়েছে।
jwww

54

স্ট্যাটিক লাইব্রেরিগুলি জড়িত থাকাকালীন জিনিসগুলি কীভাবে জিসিসির সাথে কাজ করে তা পরিষ্কার করার জন্য এখানে একটি উদাহরণ দেওয়া আছে । সুতরাং আসুন ধরে নেওয়া যাক আমাদের নিম্নলিখিত পরিস্থিতিতে আছে:

  • myprog.o- main()উপর নির্ভরশীল ফাংশনlibmysqlclient
  • libmysqlclient- স্থিতিশীল, উদাহরণের জন্য (আপনি অবশ্যই ভাগ্যযুক্ত লাইব্রেরি পছন্দ করবেন libmysqlclient) , কারণ এটি বিশাল; মধ্যে /usr/local/lib; এবং থেকে স্টাফ উপর নির্ভরশীলlibz
  • libz (গতিশীল)

আমরা কিভাবে এটি লিঙ্ক করব? (দ্রষ্টব্য: জিসিসি ৪.৩.৪ ব্যবহার করে সাইগউইনকে সংকলনের উদাহরণ)

gcc -L/usr/local/lib -lmysqlclient myprog.o
# undefined reference to `_mysql_init'
# myprog depends on libmysqlclient
# so myprog has to come earlier on the command line

gcc myprog.o -L/usr/local/lib -lmysqlclient
# undefined reference to `_uncompress'
# we have to link with libz, too

gcc myprog.o -lz -L/usr/local/lib -lmysqlclient
# undefined reference to `_uncompress'
# libz is needed by libmysqlclient
# so it has to appear *after* it on the command line

gcc myprog.o -L/usr/local/lib -lmysqlclient -lz
# this works

31

আপনি যদি -Wl,--start-groupলিঙ্কার পতাকাগুলিতে যুক্ত করেন তবে সেগুলি কোন অর্ডারে রয়েছে বা বৃত্তাকার নির্ভরতা রয়েছে তা বিবেচ্য নয়।

কিউটি তে এর অর্থ যোগ করা:

QMAKE_LFLAGS += -Wl,--start-group

গণ্ডগোলের সাথে প্রচুর সময় সাশ্রয় করে এবং এটি খুব বেশি লিঙ্ক করা ধীরে ধীরে দেখা দেয় না (যা যাইহোক সংকলনের চেয়ে অনেক কম সময় নেয়)।


8

আরেকটি বিকল্প হ'ল দু'বার গ্রন্থাগারের তালিকা নির্দিষ্ট করা:

gcc prog.o libA.a libB.a libA.a libB.a -o prog.x

এটি করার ফলে, আপনাকে সঠিক ক্রম নিয়ে বিরক্ত করতে হবে না কারণ দ্বিতীয় ব্লকে রেফারেন্সটি সমাধান হয়ে যাবে।


5

আপনি -Xlinker বিকল্পটি ব্যবহার করতে পারেন।

g++ -o foobar  -Xlinker -start-group  -Xlinker libA.a -Xlinker libB.a -Xlinker libC.a  -Xlinker -end-group 

প্রায় সমান

g++ -o foobar  -Xlinker -start-group  -Xlinker libC.a -Xlinker libB.a -Xlinker libA.a  -Xlinker -end-group 

সাবধান!

  1. একটি দলের মধ্যে ক্রম গুরুত্বপূর্ণ! এখানে একটি উদাহরণ রয়েছে: একটি ডিবাগ লাইব্রেরিতে একটি ডিবাগ রুটিন থাকে তবে নন-ডিবাগ লাইব্রেরিতে এর দুর্বল সংস্করণ থাকে। আপনাকে অবশ্যই ডিবাগ লাইব্রেরি FIRST টি গোষ্ঠীতে স্থাপন করতে হবে বা আপনি নন-ডিবাগ সংস্করণে সমাধান করবেন।
  2. আপনাকে গ্রুপ লিস্টের প্রতিটি লাইব্রেরি -Xlinker এর সাথে আগে করতে হবে

5

আমাকে দ্রুত ছড়িয়ে দেওয়ার একটি দ্রুত পরামর্শ: যদি আপনি লিঙ্কারটিকে "জিসিসি" বা "জি ++" হিসাবে আহ্বান করেন, তবে "- স্টার্ট-গ্রুপ" এবং "--end-group" ব্যবহার করে সেই বিকল্পগুলি এর মধ্য দিয়ে যাবে না লিঙ্কার - না এটি কোনও ত্রুটি চিহ্নিত করবে। আপনার যদি গ্রন্থাগারের ক্রমটি ভুল থাকে তবে এটি অপরিজ্ঞাত চিহ্নগুলির সাথে লিঙ্কটি ব্যর্থ করবে।

লিঙ্কারের মাধ্যমে যুক্তিটি পাস করার জন্য জিসিসিকে বলার জন্য আপনাকে এগুলিকে "-Wl, - start-group" ইত্যাদি লিখতে হবে।


2

কমপক্ষে কিছু প্ল্যাটফর্মে লিঙ্ক অর্ডার অবশ্যই গুরুত্বপূর্ণ। আমি লাইব্রেরিগুলির সাথে সংযুক্ত অ্যাপ্লিকেশনগুলির জন্য ক্র্যাশগুলি ভুল ক্রমে দেখেছি (যেখানে ভুল মানে A এর সাথে বিযুক্ত রয়েছে তবে B এর উপর নির্ভর করে)।


2

আমি এটি অনেক কিছু দেখেছি, আমাদের কিছু মডিউলগুলি আমাদের কোড প্লাস সিস্টেম এবং তৃতীয় পক্ষের লাইবসের 100 টি লাইব্রেরির চেয়েও বেশি সংযোগ দেয়।

বিভিন্ন লিঙ্কারগুলির উপর নির্ভর করে এইচপি / ইন্টেল / জিসিসি / সান / এসজিআই / আইবিএম / ইত্যাদি আপনি কিছু সমাধান না করা ফাংশন / ভেরিয়েবল ইত্যাদি পেতে পারেন, কিছু প্ল্যাটফর্মে আপনাকে দু'বার লাইব্রেরি তালিকাভুক্ত করতে হবে।

বেশিরভাগ অংশের জন্য আমরা লাইব্রেরিগুলির কাঠামোগত শ্রেণিবিন্যাস, কোর, প্ল্যাটফর্ম, বিমূর্ততার বিভিন্ন স্তর ব্যবহার করি তবে কিছু সিস্টেমে আপনাকে এখনও লিঙ্ক কমান্ডে আদেশ সহ খেলতে হবে।

একবার আপনি কোনও সমাধান ডকুমেন্টটি হিট করেন যাতে পরবর্তী বিকাশকারী এটি আবার কাজ করে না।

আমার প্রবীণ প্রভাষক বলতেন, " উচ্চ সংহতি এবং নিম্ন মিলন ", এটি আজও সত্য।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.