Я переношу свой рабочий код в родную Ubuntu, скомпилированную с помощью GCC/G++. В основном это было безболезненно, за исключением нескольких незначительных неприятностей. К правилам использования заглавных букв в Unix нужно привыкнуть...
Этот код работает и протестирован на нескольких других компиляторах, а также на MinGW в Windows. Однако в Ubuntu выдается действительно странная ошибка компоновщика для log(M) только в одном файле test.cpp. Журнал используется где-то ранее в том же файле и в других модулях компиляции, и компоновщик их вообще не винит. Я не знаю, как расшифровать оформление ссылок на компоновщик GCC, но кажется очень странным, что компоновщик смог удовлетворить все остальные вызовы log(), но не этот конкретный.
Если подумать об этом во время ввода этого текста, то есть небольшая вероятность того, что в этом конкретном файле он использовал идентификатор для другого вызова и вместо этого вычислил log2() (и это может быть верно и в другом месте). Если я изолирую эти фрагменты в игрушечный файл MRE, все работает отлично
В настоящее время я не могу создать минимально воспроизводимый пример, поэтому на данный момент я закомментировал некорректную строку, чтобы можно было проверить остальную часть кода на функциональность и контрольные показатели времени (он используется только для работы энтропию распределения гистограммы, чтобы она не мешала другим тестам). Игрушечная версия, в ссылках которой содержится только некорректный код, работает без ошибок и делает именно то, что должна.
Рабочий код, использующий log в test.cpp, вычисляет точное количество бит:
res = F-Fref; если (Fref != 0) rel = fabs(res/Fref); иначе отн = 0; если (rel>0) биты = log(rel)/log(0,5); еще биты = 53; // строка 344, ссылки ОК [отрывок] M = ((double) hist[j]) / total_repeats; // строка 666 если (M) s -= M * log(M); // эта строка генерирует ошибку компоновщика // M объявляется двойным M; Сообщенная ошибка следующая:
echo "Начальная ссылка" Стартовая ссылка gcc KeplerSolver.cpp -o KeplerSolver -O3 -Ofast -lm эталонный тест.o BM_shims.o BM_starter.o classic.o compilertests.ouberoot.o deltas.o intel.o MyTrig.o opt_starter.o quartic.o PadeApprox.osolver.o starter.o stdafx.otests.overify.o /usr/bin/ld:tests.o: в функции `RandomTest(int, long, bool)': tests.cpp:(.text+0x590b): неопределенная ссылка на `_ZGVbN2v_log' /usr/bin/ld:tests.cpp:(.text+0x591f): неопределенная ссылка на `_ZGVbN2v_log' Collect2: ошибка: ld вернул 1 статус выхода make: *** [Makefile:8: KeplerSolver.exe] Ошибка 1 Я не вижу ничего особенного в вызове подпрограммы, вызывающей нарушение, в журнале, который не будет разрешен в компоновщике. В моем коде сделано всего несколько вызовов log (и exp), и большинство из них объединены в пары таким образом, что компилятор может заменить их на log2 и 2^x во время оптимизации. Есть мысли о том, что может вызвать такое странное поведение во время соединения?
Предложенный ответ, связанный с тем, когда этот вопрос был закрыт, вообще не отвечает на мой вопрос. Я компоную стандартные библиотеки в основном успешно, за исключением одного единственного сбоя в test.cpp. Комментирование этой единственной строки с помощью log() приводит к успешной компиляции и связыванию.
Комментарии 1 и 2 ниже очень точны. Ответственен за порядок связывания кода и системных библиотек, и этот пост должен быть связан с Почему порядок связывания библиотек иногда вызывает ошибки в GCC? Спасибо @someprogrammerdude и @n.m.couldbeanAI за оперативную помощь.
Мобильная версия