Xanyx
Xanyx

Reputation: 111

Invalid Pointer Operation, advice requested with debugging

I appear to have created code that is trashing memory.

Having never had such problems before, i am now settign an Invalid Pointer Operation.

In the following the value of the const string sFilename gets trashed after my call to 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;

Other Details:

So I would like some advice on how to debug the issue. I was thinking perhaps watching the memory pointer where the sFilename var exists to see where it gets trashed, but not sure how i would do that (obviously needs to be done within the app so is owned memory).

Thanks

Upvotes: 3

Views: 1372

Answers (4)

Mason Wheeler
Mason Wheeler

Reputation: 84540

Sounds to me like something's trashing your stack. From a casual look at your code I can't see any obvious correctness problems. You've got the right idea: To track this down you need to monitor the value of your string and see when it changes. Here's how you do that:

  • Place a breakpoint at the first line of your method.
  • When it breaks, look at your Local Variables view in the debugger. Find sFilename and double-click on it.
  • The Debug Inspector window will open. At the top it'll say something like this: sFileame: string $18FEA8 : $4A0E5C. Those two hex values are the locations of the reference to the string and the string data itself, respectively.
  • Hit CTRL-ALT-B to bring up the Breakpoint List. It has a little toolbar, and the first button on the toolbar has a dropdown arrow.
  • Click this arrow and select Data Breakpoint from the list. You'll want to create two breakpoints, one for each of the two values in the Debug Inspector window. (If it warns you about putting a data breakpoint on the stack, do it anyway, but you'll want to remember to clear it afterwards.)
  • Once you've got the two data breakpoint values set, hit F9. The system will watch those memory locations and break when they're modified. From there you should be able to track down what's corrupting your string.

Upvotes: 6

Deltics
Deltics

Reputation: 23036

I presume that your PromptForXYZPropertiesSettings internally calls ShowModal() and if TdlgEditor is set to Free on close (FormClose event setting CloseAction := caFree) then when the flow of execution returns to your code, the dlgEditor object is already destroyed and therefore invalid.

This might also explain the invalid pointer operation, since you would be attempting to free an already Free'd object in the finally dlgEditor.Free code.

If that is the case then you should change your TdlgEditor to only hide when closed, setting CloseAction := caHide in the FormClose event.

Upvotes: 0

Viktor Svub
Viktor Svub

Reputation: 1469

I'd suspect some code in the TdlgEditor.LoadFromFile (or further down the call stack) accesses the string via pointer (in which case the compiler can't enforce the const-ness).
string/AnsiString variables are in fact ref-counted records handled by compiler intrinsic and should never be changed via pointer access.
As long as you can't change the TdlgEditor class, your solution may be actually right - you make a local copy of the string and so you don't have to care if it gets thrashed in the process, you just have to remember to not assume anything about the contents of the local string after the call.

Upvotes: 1

Alex
Alex

Reputation: 5668

Usually Invalid Pointer Operation occurs when you pass invalid pointer to MM's routines. Like freeing memory twice. Memory corruption usually results in access violation.

I think that you should start with using debugging memory manager in debug mode.

Upvotes: 0

Related Questions