OSX 10.5 Leopard Symbol Mangling с $non_lazy_ptr
Почему Леопард искажает некоторые символы с помощью $non_lazy_ptr? Что еще более важно, каков наилучший метод исправления неопределенных ошибок символов, потому что символ был искажен с $non_lazy_ptr?
5 ответов
От: Связь с разработчиком - косвенная адресация
Косвенная адресация - это имя метода генерации кода, который позволяет ссылаться на символы, определенные в одном файле, из другого файла, не требуя, чтобы файл ссылки имел явное знание макета файла, который определяет символ. Следовательно, определяющий файл может быть изменен независимо от ссылочного файла. Косвенная адресация сводит к минимуму количество мест, которые должны быть изменены динамическим компоновщиком, что облегчает совместное использование кода и повышает производительность.
Когда файл использует данные, определенные в другом файле, он создает ссылки на символы. Ссылка на символ идентифицирует файл, из которого импортируется символ, и ссылочный символ. Существует два типа ссылок на символы: неряхи и ленивые.
Нелинейные ссылки на символы разрешаются (привязываются к их определениям) динамическим компоновщиком при загрузке модуля. Неполная ссылка на символ, по сути, является символьным указателем - частью данных размером с указатель. Компилятор генерирует ссылки без задержек для символов данных или адресов функций.
Ленивые ссылки на символы разрешаются динамическим компоновщиком при первом использовании (не во время загрузки). Последующие вызовы ссылочного символа переходят непосредственно к определению символа. Ленивые ссылки на символы состоят из указателя символа и заглушки символа, небольшого количества кода, который непосредственно разыменовывается и перепрыгивает через указатель символа. Компилятор генерирует ленивые ссылки на символы, когда сталкивается с вызовом функции, определенной в другом файле.
Говоря по-человечески: компилятор генерирует заглушки с присоединенным к ним $non_lazy_ptr для ускорения ссылок. Вы, вероятно, видите, что функция Foo, на которую ссылается _Foo$non_lazy_ptr, не определена или что-то в этом роде - это не одно и то же. Убедитесь, что символ фактически объявлен и экспортирован в объектных файлах / библиотеках, с которыми вы связываете свое приложение. По крайней мере, это была моя проблема, я также думал, что это странная вещь компоновщика, пока не обнаружил, что моя проблема была в другом месте - есть несколько других возможных причин, найденных в Google.
ranlib -c libwhatever.a
является серьезным решением проблемы. У меня была такая же проблема при сборке библиотеки PJSIP для iOS. Эта библиотека использует систему make, основанную на autoconf, но требует небольшой настройки различных файлов, чтобы все было хорошо для iOS. В процессе этого мне удалось удалить строку ranlib в правиле для библиотек, а затем начал получать ошибку в ссылке моего проекта о _PJ_NO_MEMORY_EXCEPTION
по ссылке от _PJ_NO_MEMORY_EXCEPTION$non_lazy_ptr
быть неопределенным.
Добавление строки ranlib обратно в файл библиотеки решило эту проблему. Теперь моя полная запись для LIBS в rules.mak
$(LIB): $(OBJDIRS) $(OBJS) $($(APP)_EXTRA_DEP)
if test ! -d $(LIBDIR); then $(subst @@,$(subst /,$(HOST_PSEP),$(LIBDIR)),$(HOST_MKDIR)); fi
$(LIBTOOL) -o $(LIB) $(OBJS)
$(RANLIB) -c $(LIB)
Надеюсь, что это поможет и другим, пытающимся использовать общие внешние библиотеки, настроенные для UNIX, с iPhone или iOS.
Если кто-то споткнется, та же проблема, что и у меня:
Имел extern NSString* const someString;
в заголовочном файле, но забыл поставить файл реализации. как NSString* const someString=@"someString";
Это решило это.