ByteArray из библиотеки C ++ приводит к сбою Delphi в DynArrayClear - PullRequest
0 голосов
/ 31 декабря 2011

У меня все еще проблемы с тем же приложением, что и здесь Delphi CopyMemory против C ++ memcpy

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

У меня есть приложение delphi, которое использует сетевую библиотеку и серверное приложение (которое существует где-то в работе), которое использует ту же сетевую библиотеку. Сетевая библиотека, кажется, работает правильно, написана на C ++ (не мной). Библиотека обрабатывает все сообщения для меня, поэтому мне нужно только предоставить массив байтов в библиотеку. Я могу успешно отправлять и получать данные с моего сервера - и данные верны в обоих направлениях.

Я получаю данные с сервера во вспомогательной процедуре. Процедура работает правильно до «конца»; (в буквальном смысле). Процедура заканчивается (на этом этапе я успешно прошел через все коммуникации и теперь имею дело только с Delphi), и отладчик переводит меня в _DynArrayClear - где происходит сбой моего приложения. Из справки я прочитал «Компилятор Delphi автоматически вставляет вызовы этой функции, когда это необходимо».

Я добавлю еще немного фона, если это поможет ... Сетевая библиотека заполняет байтовый массив, который определен как void * data в структуре содержимого (см. Ниже)

struct content {
  void *data;
  int size;
}

Я считаю, что все, что мне нужно сделать, после заполнения этих данных, выполнить операцию CopyMemory в Delphi ...

Может ли кто-нибудь помочь мне понять, что я сделал неправильно?!

// should be: function THelper.ReceiveData: TBytes; - 
// but my crash happens with either a function or a procedure
procedure THelper.ReceiveData; 
var
  lMsg: Pointer;
  lSize: Integer;
  lData: TBytes;
  lRecvResult: Integer;
begin
  lMsg := nil;

  // Remote call to receive data returns an integer indicating success
  lRecvResult := lib_receive_data(lMsg, Integer(Flags));
  TUtils.CheckError(lRecvResult);

  SetLength(lData, 5);
  CopyMemory(@lData[0], lMsg, 5); // where 5 is the length of data to copy
end; // takes me into _DynArrayClear 



// The application crashes after exiting _DynArrayClear 
// For clarity @@noFinalize is entered at line 20795
// I get all the way to the 'end;' at line 20801 in System.pas
// 
// Then from _DynArrayClear I press F7 and immediately get access violation at 0xcdcdcdcd: read address of 0xcdcdcdcd and the following is the call stack...

:7789fada ntdll.NtQueryInformationProcess + 0x12
:77890143 ntdll.KiUserExceptionDispatcher + 0xf
:778c6a8b ; ntdll.dll
:77890143 ntdll.KiUserExceptionDispatcher + 0xf
:778c6a8b ; ntdll.dll
:77890143 ntdll.KiUserExceptionDispatcher + 0xf
:778c6a8b ; ntdll.dll
:77890143 ntdll.KiUserExceptionDispatcher + 0xf
:778c6a8b ; ntdll.dll
:77890143 ntdll.KiUserExceptionDispatcher + 0xf
:778c6a8b ; ntdll.dll
:77890143 ntdll.KiUserExceptionDispatcher + 0xf
:778c6a8b ; ntdll.dll
:77890143 ntdll.KiUserExceptionDispatcher + 0xf
:778c6a8b ; ntdll.dll

1 Ответ

0 голосов
/ 31 декабря 2011

lRecvResult: = lib_receive_data (lMsg, Integer (Flags));

Какой первый параметр lib_receive_data() фактически объявлен как? Вы передаете локальную переменную Pointer, которая изначально установлена ​​на nil, поэтому я предполагаю, что параметру является var, которому присваивается какой-то значимый адрес памяти при выходе из lib_receive_data()? Что на самом деле выводит lib_receive_data()? 1011 *

Вы имеете в виду структуру content, но я не вижу, чтобы вы использовали ее где-либо. И вы объявляете переменную lSize, но вы также не используете ее. Что на самом деле говорит документация для lib_receive_data()

SetLength (lData, 5); CopyMemory (@lData [0], lMsg, 5); // где 5 - длина данных для копирования

Вы абсолютно уверены, что lMsg всегда указывает на буфер, который содержит не менее 5 байтов? Что представляет собой возвращаемое значение lib_receive_data()? Это число байтов или просто код состояния?

Тот факт, что вы получаете ошибки по адресу, подобному 0xcdcdcdcd, говорит о том, что вы, вероятно, попираете память TBytes, что приведет к сбою в _DynArrayClear() при освобождении TBytes.

...