c - `bash:./a.out: 'ld' द्वारा निष्पादन योग्य चलने पर ऐसी कोई फ़ाइल या निर्देशिका नहीं है
linux gcc (2)
ld -lc ao
इस कमांड लाइन में कई चीजें गलत हैं:
सामान्य तौर पर, उपयोगकर्ता-स्तर कोड सीधे
ld
उपयोग नहीं करना चाहिए, और लिंक को करने के लिए हमेशा उपयुक्त कंपाइलर फ्रंट एंड (gcc
) का उपयोग करें।जैसा कि आपने पाया है, लिंक कमांड लाइन
gcc
निर्माण काफी जटिल है, और जोन एस्टेबन के उत्तर में आपने जो कमांड लाइन स्वीकार की है वह गलत हैयदि आप वास्तविक लिंक कमांड देखना चाहते हैं, तो
gcc -v ao
से आउटपुट की जांच करें।यह भी ध्यान रखें कि लिंक कमांड में काफी बदलाव होता है जब आप
gcc
कमांड को केवल थोड़ा बदलते हैं (उदाहरण के लिए, कुछ ओएस को अलग-अलगcrt1.o
आवश्यकता होती है,crt1.o
आधार पर कि क्या आप बहु-थ्रेडेड निष्पादन योग्य या नहीं जोड़ रहे हैं), और कमांड लाइन हमेशा ओएस-विशिष्ट (जो कि एक है कभी भीld
सीधे उपयोग नहीं करने के लिए अधिक कारण)पुस्तकालयों को ऑब्जेक्ट फाइलों को कमांड लाइन पर चलाना चाहिए। तो
ld -lc ao
सही नहीं है, और हमेशा होना चाहिए (एक प्रकार का)ld ao -lc
। स्पष्टीकरण
सी में एक हैलो वर्ल्ड कोड है:
// a.c
#include <stdio.h>
int main() {
printf("Hello world\n");
return 0;
}
मैं इसे gcc ac
रूप में संकलित करता हूं, जो अपेक्षित के रूप में a.out
उत्पन्न करता है और ./a.out
Hello world
प्रिंट करता है ... जैसा कि उम्मीद है
अब अगर मैं संकलन और लिंक अलग से करता हूं: gcc -c ac; ld -lc ao
gcc -c ac; ld -lc ao
, यह a.out
को। / a.out
रूप में तैयार किया जाता है मुझे संदेश मिलता है:
bash: ./a.out: No such file or directory
मैं उस त्रुटि को गोगा गया और ऐसा लगता है कि जब निष्पादन योग्य उत्पादित होता है तो वह 32-बिट ELF है और मशीन आर्किटेक्चर 64-बिट है I
मैं एक 64-बिट मशीन चला रहा हूं और file a.out
चलाने देता है:
a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), not stripped
ऐसा क्यों होता है?
संपादित करें:
uname -m
का आउटपुट
$ uname -m
x86_64
ldd a.out
आउटपुट का आउटपुट
$ ldd a.out
linux-vdso.so.1 => (0x00007ffeeedfb000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa13a7b8000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa13abab000)
gcc ac
a.out
उत्पादन करता है जो सही ढंग से चलता है।
अन्य जवाब केवल यह कैसे से बचने के लिए पता है, नहीं हुआ क्या का वास्तविक सवाल ।
gcc -c ac; ld -lc ao
gcc -c ac; ld -lc ao
कमांड्स आपको बहुत स्पष्ट चेतावनी देते हैं:
ld: warning: cannot find entry symbol _start; defaulting to 0000000000400260
इसलिए भले ही यह फाइल निष्पादित हो सकती है, यह संभवत: तुरंत दुर्घटना हो जाएगी। आप क्या करना चाहिए था की एक स्पष्टीकरण के लिए @ EmployedRussian का जवाब देखें
यह प्रश्न भी क्यों नहीं चलाया जा सकता है कि अभी भी रोचक है:
$ strace ./a.out
execve("./a.out", ["./a.out"], [/* 72 vars */]) = -1 ENOENT (No such file or directory)
execve(2)
ENOENT रिटर्न क्योंकि यह दुभाषिया नहीं मिल सकता है (जो मैं file
से बाहर सोचा और इतने पर, नीचे देखें)। आपको उसी त्रुटि को एक फ़ाइल चलाने की कोशिश करने से प्राप्त होनी चाहिए, जिसमें से शुरू हुई
#!/usr/non-existant-path/bin/bash
जैसा कि आपने पाया है, इस त्रुटि संदेश का सामान्य कारण तब होता है जब किसी एल्एफ बाइनरी को सही गतिशील लिंकर और बिना गतिशील लिंक किए गए पुस्तकालयों (जैसे कि 64 बिट सिस्टम को 32 बिट समर्थन स्थापित किए बिना) चलाया जाता है। आपके मामले में, यह इसलिए है क्योंकि आपने खराब लिंक कमांड का उपयोग किया था और खराब इंटरप्रिटर पथ के साथ गतिशील निष्पादन योग्य बनाया था।
मैं Ubuntu 15.10 पर हूं, जहां GNU file
संस्करण 5.22 रिपोर्ट करता है:
a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib/ld64.so.1, not stripped
मेरे सिस्टम पर कोई /lib/ld64.so.1
नहीं है। ldd
उत्पादन भ्रामक है, क्योंकि ldd
अपने डिफ़ॉल्ट एल्फ़ दुभाषिया का उपयोग करता है, न कि बाइनरी द्वारा निर्दिष्ट।
$ ldd a.out
linux-vdso.so.1 => (0x00007ffc18d2b000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0e0a79f000)
/lib/ld64.so.1 => /lib64/ld-linux-x86-64.so.2 (0x0000559dbc9d2000)
तो यह मानता है कि एक ldd
को हल करने वाली द्विआधारी में रनटाइम दुभाषिया का प्रयोग होता है, मुझे लगता है
आपका ldd
आउटपुट शायद एक पुराने संस्करण से भी है, क्योंकि यह सिर्फ उस लाइन के लिए / /lib64/ld-linux-x86-64.so.2
दिखाता है। बुरा अनुमान नहीं लेना संभवतः बेहतर व्यवहार है, इस तरह के एक अजीब मामले के लिए, लेकिन आपको यह देखने में मदद नहीं करता कि आपके बाइनरी में एक अजीब व्याख्याता पथ है।
readelf -l a.out
आपके लिए ईएलएफ शीर्षकों को व्याख्यान देगा, जिसमें दुभाषिया पथ भी शामिल है। (यह इंगित करने के लिए @ कार्यरत रूसी की टिप्पणी के लिए धन्यवाद।)