Недопустимая операция с указателем, запрашивается совет при отладке - PullRequest
2 голосов
/ 01 июня 2010

Я, кажется, создал код, который загружает память.

Никогда раньше таких проблем не было, теперь я настроен на недопустимую операцию указателя.

В дальнейшем значение константной строки sFilename удаляется после моего вызова PromptForXYZPropertiesSettings.

// Allow the user to quickly display the properties of XYZ without needing to display the full Editor
function PromptForXYZProperties(const sFilename:string; var AXYZProperties: TXYZProperties): boolean;
var
  PropEditor: TdlgEditor;
begin
  PropEditor:= TdlgEditor.create(nil);
  try
    PropEditor.LoadFromFile(sFilename);                   <-- sFilename = 'C:\My Folder\Some Folder.txt'
    PropEditor.SelectedXYZProperties := AXYZProperties;

    // Bypass PropEditor to show form owned by it
    Result := PropEditor.PromptForXYZPropertiesSettings;  

    if Result then
    begin
      PropEditor.SaveToFile(sFilename);                   <-- sFilename now somethign like 'B'#1#0#0'ë' or value of a different var
    end;
  finally
    PropEditor.free;      
  end;
end;

Другие детали:

  • Delphi 2007, Windows 7 64 бит, но можно воспроизвести при тестировании EXE на XP
  • УДАЛЕНИЕ КОНСТОВ ОСТАНАВЛИВАЕТ ПРОБЛЕМУ С ВЫСТАВКИ (но предположительно проблема, таким образом, просто скрывается)
  • PropEditor.PromptForXYZPropertiesSettings создает и показывает форму. Если я отключить вызов ShowModal, то память не разгромлена. Хотя я УДАЛЕНЫ ВСЕ УПРАВЛЕНИЯ И КОД из формы

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

Спасибо

Ответы [ 4 ]

6 голосов
/ 01 июня 2010

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

  • Поместите точку останова в первую строку вашего метода.
  • Когда он сломается, посмотрите на представление Local Variables в отладчике. Найдите sFilename и дважды щелкните по нему.
  • Откроется окно Инспектора отладки. Вверху он скажет что-то вроде этого: sFileame: string $18FEA8 : $4A0E5C. Эти два шестнадцатеричных значения являются местоположениями ссылки на строку и сами данные строки соответственно.
  • Нажмите CTRL-ALT-B, чтобы вызвать список точек останова. Он имеет небольшую панель инструментов, а первая кнопка на панели инструментов имеет стрелку раскрывающегося списка.
  • Нажмите эту стрелку и выберите точку останова данных из списка. Вы захотите создать две точки останова, по одной для каждого из двух значений в окне инспектора отладки. (Если он предупреждает вас о размещении точки останова данных в стеке, сделайте это в любом случае, но вы не забудете очистить ее позже.)
  • Как только вы установили два значения точки останова данных, нажмите F9. Система будет следить за этими ячейками памяти и ломаться при их изменении. Оттуда вы сможете отследить, что портит вашу строку.
1 голос
/ 01 июня 2010

Я подозреваю, что некоторый код в TdlgEditor.LoadFromFile (или далее вниз по стеку вызовов) получает доступ к строке через указатель (в этом случае компилятор не может применить const -ness).
string / AnsiString переменные на самом деле являются записями с пересчетом, которые обрабатываются встроенным компилятором и никогда не должны изменяться через доступ по указателю.
Пока вы не можете изменить класс TdlgEditor, ваше решение может быть действительно правильным - вы делаете локальную копию строки, и вам не нужно беспокоиться о том, что она будет разбита в процессе, вам просто нужно не забудьте не предполагать что-либо о содержимом локальной строки после вызова.

0 голосов
/ 01 июня 2010

Я предполагаю, что ваш PromptForXYZPropertiesSettings внутренне вызывает ShowModal(), а если TdlgEditor установлен на Свободно при закрытии (FormClose установка события CloseAction := caFree), то когда поток выполнения возвращается к вашему коду, dlgEditor объект уже уничтожен и поэтому недействителен.

Это также может объяснить недопустимую операцию указателя, поскольку вы пытаетесь освободить уже Free d-объект в коде finally dlgEditor.Free.

Если это так, то вы должны изменить TdlgEditor на скрытие только в закрытом состоянии, установив CloseAction := caHide в событии FormClose.

0 голосов
/ 01 июня 2010

Обычно операция неверного указателя происходит, когда вы передаете недопустимый указатель на процедуры MM. Как освобождение памяти в два раза. Повреждение памяти обычно приводит к нарушению доступа.

Я думаю, что вам следует начать с использования отладчика диспетчера памяти в режиме отладки .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...