Почему мой параметр, передаваемый по ссылке, не изменяется внутри функции?

StackOverflow https://stackoverflow.com/questions/148024

Вопрос

У меня есть функция C в статической библиотеке, назовем ее A, со следующим интерфейсом:

int A(unsigned int a, unsigned long long b, unsigned int *y, unsigned char *z);

Эта функция изменит значение y и z (это точно).Я использую его из динамической библиотеки C++, используя extern "C".

Теперь вот что меня поразило:

  • y установлен правильно, z не изменен.Я имею в виду, что если оба инициализируются (указанным) значением 666, значение, указанное y, изменится после вызова, но не значение, указанное z (все еще 666).
  • При вызове из бинарного файла эта функция работает плавно (значение, указанное z, модифицировано).
  • если я создаю фиктивную библиотеку C с функцией, имеющей тот же прототип, и использую ее из своей динамической библиотеки C++, она работает очень хорошо.Если я повторно использую те же переменные для вызова A(..), я получаю тот же результат, что и раньше, z не изменяется.

Думаю, приведенные выше пункты показывают, что это не глупая ошибка с объявлением моих переменных.

Я явно застрял и не могу изменить библиотеку C.Есть ли у вас какие-либо идеи о том, в чем может быть проблема?Я думал о проблеме в интерфейсе C/C++, например, о том, как интерпретируется символ *.

Редактировать :Наконец-то я узнал, в чем проблема.Смотрите ниже мой ответ.

Это было полезно?

Решение 9

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

Короткий ответ на мою проблему:Проблема заключалась в том, что моя библиотека C++ использовала старую версию библиотеки C.В этой старой версии пропущен четвертый аргумент.Как следствие, четвертый аргумент, очевидно, никогда не менялся.

Теперь мне немного стыдно, что я понял, что это была проблема.Однако меня ввел в заблуждение тот факт, что мой код компилировался нормально.Это произошло из-за того, что библиотека C++ скомпилировалась с правильной версией библиотеки C, но во время выполнения она использовала старую версию, статически связанную с другой библиотекой, которую я использовал.

C++ Lib (M) ---> dyn C++ lib (N) ---> C lib (P) v.1.0
     |
     ------> C lib (P) v.1.1

(N) — динамическая библиотека, статически скомпонованная с (P) версии 1.0.Компилятор принял вызов (M) к функции с 4 аргументами, поскольку я связался с (P) версии 1.1, но во время выполнения он использовал старую версию (P).

Не стесняйтесь редактировать этот ответ или вопрос или просить меня сделать это.

Другие советы

Похоже, это разница между тем, как ваша библиотека C и компилятор C++ работают с длинные лонги.Я предполагаю, что библиотека C, вероятно, является стандартом до C89 и фактически обрабатывает 64-битную версию. долго долго длиной 32 бита.Ваша библиотека C++ правильно обрабатывает это и помещает 64 бита в стек вызовов и, следовательно, повреждает y и z.Возможно, попробуйте вызвать функцию через *int A(unsigned int a, unsigned long b, unsigned int *y, unsigned char з), и посмотрите, что у вас получится.

Просто мысль.

Это один из тех вопросов, в которых нет ничего очевидно неправильного из того, что вы описали, но все работает не так, как вы ожидаете.

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

  • Для какой платформы этот код:Windows, Linux, что -то встроенное или ...?
  • С какой компилятором построена Статическая библиотека C?
  • Каким компилятором построена динамическая библиотека C ++?
  • Какой компилятор C, который может успешно вызвать библиотеку, построенную?
  • У вас есть отладчик на уровне источника?Если так, можете ли вы шагнуть в C -код из C ++.

Если вы не ошибаетесь в том, что A всегда изменяет данные, на которые указывает Z, единственной вероятной причиной вашей проблемы является несовместимость между соглашениями о передаче параметров.Проблема «долго-долго» может быть намеком на то, что все не так, как кажется.

В крайнем случае, вы можете сравнить дизассемблированный код вызова C++ (который, по вашим словам, терпит неудачу) и код вызова C (который, как вы говорите, успешен), или пройтись по инструкциям ЦП с помощью отладчика (да, действительно - вы изучите хорошие навыки, а также решение проблемы)

Насколько я знаю, long long не является частью стандарта C++, возможно, это источник вашей проблемы.

Не знаю.Попробуйте выполнить отладку в A и посмотрите, что произойдет (предупреждение ассемблерного кода!)

Может быть, вы можете обернуть исходную функцию в библиотеку C, которую вы вызываете из библиотеки C++?

Судя по вашим пунктам 2 и 3, похоже, это может сработать.

Если это не так, это дает вам еще одну точку отладки, чтобы найти больше подсказок - посмотрите, в какой из ваших библиотек первым всплывает сбой, и проверьте, почему 2 и 3 работают, а эта нет - какова минимальная разница?

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

Шаг 1:Сравните указатели y и z, переданные со стороны C++, с указателями, полученными функцией C.

P.S.Я не хочу показаться очевидным, но просто перепроверяю здесь.Полагаю, когда вы говорите, что z прекрасно изменяется при вызове из двоичного файла C, вы имеете в виду, что данные, на которые указывает z, изменяются очень хорошо.Сами указатели y и z передаются по значению, поэтому их нельзя изменить.

Еще одна дикая догадка:вы уверены, что связываетесь с правильным экземпляром функции в вашей библиотеке C?Может быть, в ваших библиотеках есть несколько таких функций?В C компоновщик не заботится о типе возвращаемого значения или списке параметров при принятии решения о том, как разрешить функцию — важно только имя.Итак, если у вас есть несколько функций с одним и тем же именем...

Вы можете программно проверить подлинность функции.Создайте библиотеку C, которая вызывает вашу функцию A с некоторыми тестовыми параметрами, работает нормально и печатает указатель на функцию A.Свяжите библиотеку с вашим приложением C++.Затем напечатайте указатель на исходную функцию A, как видно из кода C++, и сравните указатель с указателем, видимым вашей библиотекой C при вызове в том же процессе.

Опять же, очевидное, но кто знает...Вы уверены, что вызываемая вами функция C не имеет состояния, то есть ее выходные данные зависят только от входных данных?Если функция не имеет состояния, возможно, «скрытое» состояние отвечает за другое поведение (не изменяя данные, на которые указывает z) функции при вызове из вашего приложения C++.

В вашей программе на C++ объявлен ли прототип с помощью extern "C"?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top