Вызов Delphi COM-объекта в C # создает исключение AccessViolationException - PullRequest
0 голосов
/ 10 декабря 2018

Я пытаюсь отправить строку в COM-объект Delphi и ожидаю ответа от объекта, но по какой-то причине он вызывает исключение AccessViolationException.Это исключение, которое он выдает, описание исключения, переведенное на английский язык: Попытка чтения или записи в защищенную память.Это часто указывает на то, что другая память повреждена.Вывод программы (с трассировкой вершины стека):

QManservice запущен.
Нажмите любую клавишу для остановки.
Запрос на получение полученных заказов.
Полученная строка: S $ GET ORDERS,

Onnverwerkte uitzondering: System.AccessViolationException: Поиск полной суммы из Schrijven van beveiligd geheugen.Вы должны знать, что это так.

bij Microsoft.Win32.Win32Native.SysStringByteLen (IntPtr bstr)
bij System.StubHelpers.BSTRMarshaler.ConvertToManaged (IntPtr bstr)
bij QMan_SafanDarley.SM (Ответ на запрос, StringM.1013 * bij WorkLoadManagerServiceDefinitions.QManService.SendStringtoCON (String codToSend) в проектах D: \ Michael \ C # \ QManServiceConsoleApp \ OrderEditor_WCF \ QManService.cs: переадресация вызовов на объекте 210 * 1014-го класса (специалист по маркетингу);\ QManServiceConsoleApp \ OrderEditor_WCF \ QManService.cs: regel 67 ...

Этот код вызывает COM

private string SendStringToCOM(string cmdToSend)
    {
        try
        {
            Console.WriteLine($"String received: {cmdToSend}");
            if (WLM == null)
            {
                WLM = new WLM_();
            }
            string answer = string.Empty;
            WLM.Send(cmdToSend, out answer);
            Console.WriteLine("Answer received");
            return answer;
        } catch(Exception e)
        {
            Console.WriteLine(e.Message);
            Console.ReadKey();
            return string.Empty;
        }
    }

Это код в Delphi, принимающий вызов., он отправляет его другому устройству, которое выполняет работу с базой данных в соответствии с полученной командой.

function TWLM_.Send(const Msg: WideString; out Answer: WideString) : Integer;
begin
    Result := fmProduction.AnalyzeData(Msg, 0);
end;

Я должен добавить, что это работает на моем компьютере и компьютере коллеги, но не на третьем компьютере.Любые предложения о том, как я могу решить эту проблему?

Ответы [ 2 ]

0 голосов
/ 10 декабря 2018
function TWLM_.Send(const Msg: WideString; out Answer: WideString) : Integer;
begin
    Result := fmProduction.AnalyzeData(Msg, 0);
end;

Здесь вы ничего не назначаете параметру Answer.Это передается как параметр out, означающий, что метод должен назначить что-то ему.Это ведет себя точно так же, как возвращаемое значение функции.

Если вы ничего не назначите этой переменной, она будет иметь любое (неназначенное) значение, которое существовало в стеке в тот момент, когда метод выделил для него пространство стека.Это не будет действительный указатель на WideString, но потребительский код попытается упорядочить его, как если бы он был.Иногда это происходит сразу же, иногда нет, иногда может просто повредить другие данные.В любом случае это ошибка.

В нативном коде Delphi вы можете использовать параметры out и var , ведущие себя примерно одинаково - в обоих случаях для ссылочных типов указатель вызывающего кода доступен для чтения изапись методом, принимающим параметр.Если метод решает не изменять значение, это не требуется.Однако при управляемом взаимодействии ожидается, что метод всегда будет назначать параметр out.C # обеспечивает это, а Delphi - нет.

В этом случае пустая строка, которую вы передали на стороне C #, вообще не передается методу - вы можете ожидать, что она останется пустой строкой, не измененной кодом Delphi, но сделавпараметр, параметр out, вызывающий код ожидает получить возвращаемое значение в этом параметре и немедленно перезаписывает переданную переменную тем, что возвращается (в данном случае указателем на бессмыслицу).Любое значение, которое переменная на стороне C # могла иметь до передачи этому методу, будет, по расширению, недоступно на стороне Delphi / COM.

0 голосов
/ 10 декабря 2018
Комментарий

@ J ... о том, что параметр ответа не был назначен, был, в моем случае, проблемой.Я попросил коллегу изменить dll, чтобы присвоить значение параметру, и это, кажется, исправляет ошибку, и теперь она работает так, как положено.

...