2013-03-18 6 views
0

안녕하세요 세계 cpp 파일이 있습니다. c++ test.cpp -o test으로 컴파일하면 "test"파일이 실행 가능하고 (-rwxr-xr-x), 실행하면 예상 결과가 생성되어 실행됩니다.실행 파일을 실행할 수없는 이유는 무엇입니까?

그러나 내가 ${CXX} -std=c++0x -I${INCLUDE_DIR1} -c test.cpp -o test -L{LIB_DIR1} -llib_name을 사용하면 "테스트"파일을 얻지 만이 경우에는 실행이 불가능합니다. 그래서 나는 그것을 실행할 수 없다. 내가 chmod +x하려고했는데, 실행 권한이 있지만 실행하려고하면 오류 메시지가 나타납니다 (실행할 수 없습니다).

내가 뭘 잘못하고 어떻게 해결할 수 있습니까?

+0

'file test' 어떤 파일인지 확인하십시오. 아마 .o 파일의 이름이 잘못되었습니다. –

+0

'file test'라고 입력하면'test : ELF 64 비트 LSB relocatable, x86-64, version 1 (GNU/Linux), 스트립되지 않음 '을 얻었지만 의미가 무엇인지 모르겠습니다. 이 출력 결과에 "mis-named .o file"이 있다는 의미입니까? – Roman

답변

18

-c이 아니고은 컴파일러에게 실행 파일을 생성하지 않는다는 것을 의미합니다 ("컴파일 만"을 의미 함). 실행 파일 (다른 오브젝트 파일 및 라이브러리 포함)에 링크되는 데 적합한 오브젝트 파일 만 작성합니다.

실행 파일을 원할 경우 -c 스위치를 제거하십시오.

전체 컴파일 과정에 대한 자세한 내용은 다음을 참조하십시오이 전체 프로그래밍 광기의 시작에있어 같은 How does the compilation/linking process work?

+0

-c를 제거하면'/ usr/bin/ld : -llib_name collect2 : 오류 : ld가 1 종료 상태를 반환했습니다 .'라는 메시지가 나타납니다. – Roman

+0

이것은 컴파일러가 해당 라이브러리를 찾을 수 없다는 것을 의미합니다. 기본 검색 경로에 없다면,'-L/path/to/lib'로 위치하는 디렉토리를 지정해야합니다. – Mat

1

보인다. 따라서 파일 이름이 잘못 지정된 객체 (이 경우 .o) 파일, 컴파일러 매개 변수 및 라이브러리가 실제로하는 일이나 라이브러리 이름을 파악하는 데 어려움을 겪고 있다면 이해합니다.

제 가정은 알 수없는 예제 (-llib_name)에서 실행 파일을 생성하기 위해 실행중인 쉘 스크립트 행을 복사 한 것입니다. 그래서 나는 여기에서 진행되는 모든 일을 간단하고 명확하며 대략적으로 설명하려고 노력할 것입니다.

우선, C++ 컴파일러는 지정된 소스 파일을 변동 가능 머신 코드로 컴파일합니다. 컴파일러 (및 컴파일러 만)를 파일에 저장하면이 파일은 앞서 설명한 객체 파일이됩니다 (.o 파일 기억). 주의를 기울 였다면 오브젝트 파일에 재배치 가능한 머신 코드이 포함되어 있습니다.

이제 소스 코드를 컴파일했고 해당 기계어 코드를 객체 파일에 저장했습니다. 그러나이 오브젝트 파일은 직접 실행 가능하지 않습니다. 이어도에는 CPU가 실행에 문제가없는 기계어 코드가 들어 있습니다. 문제는이 기계 코드가 연결되어 있지 않다는 것입니다. 따라서 여기에 두 번째 글 머리 기호가 나온다 : 오브젝트 파일의 재배치 가능한 머신 코드는 링크되어 있지 않으므로 (잘 ~하지 말아야)을 실행할 수 없다. 이 외에도 객체 파일에는 링커가 실제 실행 파일을 생성하는 연결 프로세스를 돕기위한 추가 메타 데이터가 포함될 수 있습니다. 우리는이 중간 표현의 전체를 이라고 부르고 객체 코드는입니다.

이제 우리는 소스 코드를 컴파일하고 객체 파일을 생성 했으므로 다음 명백하고 논리적 인 단계는 객체 파일을 원하는 라이브러리 및/또는 다른 객체 파일과 연결하여 실행 파일을 생성하는 것입니다. 처음으로 ./test 바이너리처럼 실행할 수 있습니다. 이것은 링커가 작동하는 곳이며, 링커는 오브젝트 파일과 라이브러리를 받아들입니다 (사이드 노트 : 대략 라이브러리는 오브젝트 파일의 모음입니다). 모듈 간의 오브젝트 파일에서 정의되지 않은 참조를 해결하고 실행 파일 등그러면 링커는 링커가 호출 된 대상 플랫폼의 실행 가능 파일 형식을 준수하는 최종 실행 파일을 내 보냅니다. ./test처럼 실행할 수있는 것은이 파일입니다.

이제 기본 내용을 알았으므로 셸 호출에 어떤 문제가 있는지 살펴 보겠습니다. 우선, c++을 호출하면 C++ 컴파일러 (이 경우 g++ 또는 clang++)가 트리거 될 수 있음을 알아야합니다. 링커. 둘째로, -c 플래그는 컴파일러에게 주어진 소스 파일을 컴파일하고 해당 오브젝트 코드와 기계어 코드 만 출력하도록 알려줍니다. 따라서없이 을 호출하면 -c 플래그가 지정된 소스 코드를 컴파일 할뿐만 아니라 결과 객체 코드를 링크하고 최종 실행 파일을 생성합니다. 이것은 첫 번째 명령 행에서 일어나는 일입니다. test이라는 이름의 파일이 링크 된 실행 파일입니다. 그러나 두 번째 명령 줄에는 -c 플래그가 있습니다. 이 경우 컴파일러는 test.cpp을 컴파일하여 생성 된 객체 코드 만 내보내고 있습니다. 실행 파일을 생성하려면이 결과 오브젝트 파일을 링크해야합니다. 컴파일러에게 생성 된 객체 코드를 test이라는 파일에 저장하도록 지시하는 것처럼 보입니다. Marc가 잘못된 이름을 언급했을 때 (객체 파일의 대개 .o 또는 .obj 접미사가 있음) 언급 한 내용입니다.

이 시점부터 -c 플래그를 제거하거나 개체 파일을 연결하는 두 가지 옵션이 있습니다. (별도) 오브젝트 파일을 컴파일 및 링크하려면 (포함을 아마 - 그것 박사 - - 수 -가 ™liblib_name) :

${CXX} -std=c++0x -stdlib=libc++ -I${INCLUDE_DIR1} -c test.cpp -o test.o 
${CXX} -std=c++0x -stdlib=libc++ -L${LIB_DIR1} -llib_name test.o -o test 

내가 거기 libc++ 도입의 자유를 촬영했다. C++ 11 (C++ 0x로 참조)을 사용하고자한다면 주변에있는 것이 더 좋습니다. 컴파일하고 하나 개의 라인에 연결하려는 경우에는 같은 일이를 사용하여 달성 할 수 있습니다

${CXX} -std=c++0x -stdlib=libc++ -I${INCLUDE_DIR1} -L${LIB_DIR1} -llib_name test.cpp -o test 

이 두 가지가 똑같은 일을. 그러나 한 줄짜리 버전에 -c 플래그가없는 점에 유의하십시오.

거의 모든 내용을 다루었으므로 마지막 문제는 -I, -L-l입니다. -I은 컴파일러가 소스 코드에 포함 된 헤더 파일을 검색 할 경로를 지정합니다. 이 경로는 컴파일러의 기본 헤더 검색 경로를 덮어 쓰지 않으며, 단지 추가 된 것입니다. -L은 라이브러리와 동일한 내용이지만 컴파일러는이 경로에서 명시 적으로 링크하는 라이브러리 (이 경우 liblib_name 등)를 찾습니다. 다시 이것은 기본 라이브러리 검색 경로를 대체하지 않습니다. 마지막으로 -l 플래그는 실행 파일을 링크하는 동안 연결할 링커에 라이브러리를 지정하는 데 사용됩니다. 귀하의 경우에는 liblib_name (-l 플래그에 지정된 이름이 라이브러리 파일 이름의 첫 번째 lib을 생략 함) 컴파일러가 존재하지 않는다고 불평하는 라이브러리에 연결되어 있습니다. 실제로 실행 파일에 liblib_name을 연결 하시겠습니까? 이것은 심지어 진짜 도서관입니까? 그렇지 않다면, 전체 -llib_name 매개 변수를 제거하십시오. 그러면 컴파일러는 컴파일러가 그에 대해 소리 지르는 것을 멈춰야합니다.

길고 길고 긴 설명을 드려 죄송합니다.하지만 여기있는 한 마디와 한 마디를 배웠 으면 좋겠어요.이 모든 것이 당신에게 유용 할 것입니다.

관련 문제