2016-05-15 2 views
-5

В настоящее время я прочитал статью о имя mangling на wikipeida (link). В этой статье я узнаю, что общая идиома extern "C" используется для защищает эти C-коды в исходном файле C++ от искажений, что делает эти исходные коды несовместимыми для привязки к исходному C lib.Почему моя моя программа на C++ корректно связана при замене libstdC++ с помощью libgcc

Так что я сделать следующее рассуждение:

Если я пишу такой код:

#include<stdio.h> 
int main() 
{ 
    printf("Hello World\n"); 
    return 0; 
} 

и компилировать это с командой g++ test.cpp -o test, то он будет успешно скомпилировать без сомнения. Нам не нужно прилагать printf() с extern "C", хотя printf() является функцией C. Это потому, что, есть еще printf() в libstdc++, который отличается от libgcc.

До сих пор так хорошо.

Но я обнаружил, что это не так верно, как я думаю.

Я выполнить несколько экспериментов:

Я удалить все libstdc++ под /USR/Lib, которые включают в себя

  • /usr/lib/gcc/x86_64-linux-gnu/4.8/ libstdC++.
  • /usr/lib/gcc/x86_64-linux-gnu/4.8/libstdc++.so
  • /usr/lib/x86_64-linux-gnu/libstdc++.so.6
  • /USR/Lib/x86_64-ли Nux-гну/libstdC++. so.6.0.19

, а затем я сделать копию libgcc и поместить его под местом, где libstdc++ жил (в противном случае компоновщик жалобы о libstdC++ не найден)

$ Судо ф ./gcc/x86_64-linux-gnu/4.8/libgcc.a ./gcc/x86_64-linux-gnu/4.8/libstdc++.a

Однако приведенный выше код компиляции, безextern "C" !!!

Почему? не должен ли он выкидывать Неразрешенный справочник или что-то подобное, потому что printf(), которые были искажены компилятором C++, несовместимы с printf() в li libgcc?


любой скажите мне, почему мой вопрос сведется вниз?


+0

Как 'ехЬегп "C"' "известный"? –

+0

@ Daniel Kamil Kozar Я действительно не знаю, но на этой вики-странице он назывался «common C++ idiom» – walkerlala

+0

Возможно, он пытается связать с общей библиотекой '/ usr/lib/x86_64-linux-gnu/libstdC++ .so.6.0.19'. Вам нужно добавить флаг для связывания статически. PS вам не нужно было перемещать этот lib, есть опция компилятора, которая удаляла библиотеки по умолчанию из команды link. –

ответ

0

g ++ замечает, что вы компилируете что-то с помощью.c и рассматривать его как исходный файл C.

Make g++ compile C using gcc rules

Вместо удаления библиотек из системы, которая имеет хороший шанс идти не так в каком-то момент, используйте GCC флаги для печати библиотечного поиска путей и посмотреть, что происходит. Вы также можете быть заинтересованы в nm (который печатает реальные имена символов в использовании), C++ filter (который указывает имена) и ldd (который печатает связанные с ним библиотеки).

+0

Фактически я сохраняю этот файл с расширением '.cpp'. Просто неправильное обращение – walkerlala

+0

и, конечно же, я делаю копию этих 'libstdC++' – walkerlala

3

Ваш extern "C" присутствует, хотя и скрыт.

Если вы смотрите в stdio.h, вы заметите линию

__BEGIN_DECLS 

(строка 29 в моей системе *), которая, в свою очередь, расширяет к

# define __BEGIN_DECLS  extern "C" { 

(строка 98 в sys/cdefs.h на моей системе), если вы компилируете в режиме C++ и ничего не значит. Поэтому стандартный заголовок библиотеки делает для вас обертку.

Удаление стандартных библиотек C++ не имеет никакого эффекта, поскольку эти функции C живут в стандартной библиотеке C, и, поскольку все завершение выполняется правильно, компоновщик может их найти и использовать.

Теперь, конечно, это деталь реализации, в общем случае использование <stdio.h> должно работать, потому что стандарт говорит так (в настоящее время он устарел). Как достигается компилятор, который не является обязательным.


* gcc6.1.1 упаковывают для Arch Linux