Переопределить функцию C, определенную в статической библиотеке - PullRequest
7 голосов
/ 04 ноября 2011

У меня есть статическая библиотека файлов C, скомпилированная с g ++ на Cygwin. Я хочу провести модульное тестирование одной функции, определенной в библиотеке. Эта функция вызывает другую функцию, определенную в этой библиотеке, и я хочу переопределить зависимость, чтобы заменить ее собственной версией этой функции. Я не могу изменить то, что находится в статической библиотеке, поэтому это решение [ Переопределить вызов функции в C ] не применимо.

Обычно я могу написать файл .cpp и включить файл .c, содержащий функцию, которую я хочу выполнить модульное тестирование, что существенно расширяет этот файл кодом, который я добавляю. Это грязный трюк, который я бы никогда не использовал для производственного кода, но он удобен для модульного тестирования C-файлов, потому что он дает моему тестовому коду доступ к статическим объектам в C-файле. Затем я могу написать в своей фальшивой версии зависимости и моей функции модульного теста, которая вызывает функцию, которую я тестирую. Я компилирую my.cpp, чтобы получить my.o, затем связываю его со статической библиотекой. Теоретически, поскольку компоновщик уже нашел определение зависимости (которое я предоставляю), он не будет искать в библиотеке и не будет конфликта. Обычно это работает, но теперь я получаю ошибку «множественное определение», когда компоновщик сначала находит мою фальшивку, а затем находит настоящую. Я не знаю, что может вызвать это, и не знаю, что искать. Я также не могу свести это к простому примеру, потому что мои простые примеры не имеют этой проблемы.

Идеи, пожалуйста?

Ответы [ 3 ]

5 голосов
/ 04 ноября 2011

Одна возможность (правда, и некрасиво, но ...) заключается в извлечении отдельных объектных файлов из статической библиотеки.Если функция, которую вы вызываете, и функция , которую она вызывает , находятся в отдельных объектных файлах, вы можете ссылаться на объектный файл, содержащий функцию, которую нужно вызвать, но не на файл, содержащий функцию, которую она вызывает.

Это дает вам степень детализации только на уровне полных объектных файлов, поэтому, если обе задействованные функции находятся в одном объектном файле, это не сработает.Если вам действительно нужно заставить вещи работать, и вы не против сделать действительно незначительную модификацию рассматриваемого объектного файла, вы можете иметь возможностьиспользуйте бинарный редактор, чтобы пометить вторую функцию как слабую внешнюю, что означает, что она будет использоваться в отсутствие любой другой внешней среды с таким же именем, но если будет предоставлена ​​другая, вместо нее будет использоваться

То, что последнее квалифицируется как «изменение библиотеки» или нет, зависит от вашей точки зрения.Он не изменяет код в библиотеке, но изменяет немного обертки объектного файла вокруг этого кода.Я предполагаю, что вы бы предпочли этого не делать, но это все же может быть самым чистым выходом из иного невыносимого положения.

0 голосов
/ 04 ноября 2011

В зависимости от вашей платформы и требований к производительности, вы можете использовать pin для динамического изменения приложения и замены одной функции другой во время выполнения.

Прямого примера ввручную, но вы можете легко изменить один из примеров инструментов булавки, чтобы сделать это.

0 голосов
/ 04 ноября 2011

Оказывается, причина, по которой компоновщик нашел оба определения функции, заключается в том, что исходный файл фальшивой функции определил переменную, которая была вставлена ​​в его заголовочный файл. Это неразрешенное внешнее в заголовочном файле заставило компоновщик связать объектный файл фальшивой функции (все это) с файлом протестированной функции внутри библиотеки. Таким образом, невозможно извлечь определение тестируемой функции без определения зависимости.

То, что я закончил, было похоже на Переопределение вызова функции в C , где я использовал другое имя функции вместо того же и директиву препроцессора, чтобы поменять их местами. Я поместил директиву препроцессора и фальшивую функцию в отдельный файл, который может быть включен в модульный тест, поэтому нет необходимости касаться рабочего кода в библиотеке. Кроме того, если я хочу подделать эту же функцию для другого модульного теста где-нибудь еще, я могу повторно использовать новый файл.

...