Я сталкиваюсь с совершенно странной проблемой со sprintf в C, которая выходит за рамки моих базовых способностей к отладке.По сути, я использую простую структуру модульных тестов (CuTest), чтобы добавить некоторые тесты в некрасивую (недокументированную, без модульных тестов) базу кода.Я добавил новый тип модульного теста, который в основном дублирует уже существующие, но для 64-битных целых чисел, используемых в коде.
Этот тест в целом работает (правильно оценивает сравнения на равенство), но при неудаче не выдает правильное сообщение об ошибке из-за проблемы sprintf.Функция выглядит следующим образом:
/* Comparison Function for U64 Numbers */
void CuAssertU64Equals_LineMsg(CuTest* tc, const char* file, int line, const char* message, u64 expected, u64 actual) {
char buf[STRING_MAX];
if (expected == actual) return;
sprintf(buf, "expected <%lld> but was <%lld>", expected, actual);
CuFail_Line(tc, file, line, message, buf);
}
(Примечание: STRING_MAX равен 512, поэтому он должен быть достаточно большим).(Примечание 2: В системе Cygwin, с которой я сейчас работаю, u64 - это переменная «long long int»)
Если этот тест не пройден, полученное сообщение об ошибке является странной частью.Независимо от значения «фактического», он печатает 0 в этом месте.Таким образом, с учетом ожидаемого = 1 и фактического = 2 сообщение будет выглядеть следующим образом:
"expected <1> but was <0>"
Если вы измените положения аргументов и сделаете так, чтобы в них было что-то вроде:
sprintf(buf, "actually <%lld> but expected <%lld>", actual, expected);
Выполучим вывод:
"actually <2> but expected <0>"
Излишне говорить, что это имеет очень мало смысла и, возможно, указывает на какую-то странную ошибку стека, может быть?Честно говоря, я просто не совсем понимаю, как такая ошибка может произойти, даже в принципе.Я сделал небольшой рабочий пример с кодом CuTest, и он работал должным образом (не устанавливал второй в ноль).Это указывает на то, что ни CuTest, ни сама функция не являются проблемой.
Однако при использовании с реальной базой кода возникает эта проблема.Проблема связана со средой (стеком, памятью или переменными).
Кто-нибудь знает, почему это может произойти?Мои текущие теории-кандидаты: 1. Переполнение / переполнение в функции sprintf при попытке чтения данных.Я не уверен, как это произойдет, поскольку любые данные, передаваемые в функцию, являются значениями.Более того, сами данные явно существуют - я могу видеть каждое значение, если меняю порядок.
Я каким-то образом использую неправильное форматирование.Я был почти уверен, что lld был верным для длинного длинного целого (и работает в моем минимальном рабочем примере), но, возможно, он хрупок.
Полная ошибка в стеке какого-то рода.Надеюсь, что это не так, потому что я работаю над этим проектом 20 часов в неделю.Я сомневаюсь, что смог бы отладить всю кодовую базу, чтобы выяснить что-то такого масштаба.
В настоящее время я компилирую с использованием gcc-3 в среде cygwin, чего бы это ни стоило.Любые предположения были бы хорошими, я знаю, что в принципе невозможно точно диагностировать это, не видя всей базы кода, но даже некоторые рекомендации по отладке такого рода проблем были бы хороши.