world peace
world peace

Reputation: 147

delphi invalid pointer operation

Here I have a few lines of delphi code running in delphi 7:

    var
      ptr:Pointer ;
    begin
      ptr:=AllocMem(40);
      ptr:=Pchar('OneNationUnderGod');
      if ptr<>nil then
        FreeMem(ptr);
    end;

Upon running this code snippet, FreeMem(ptr)will raise an error:'invalid pointer operation'. If I delete the sentence:

     ptr:=Pchar('OneNationUnderGod');

then no error will occur. Now I have two questions,

1.Why is this happening? 2. If I have to use the Pchar sentence, how should I free the memory allocated earlier?

Much appreciation for your help!

Upvotes: 3

Views: 4644

Answers (3)

David Heffernan
David Heffernan

Reputation: 612784

The problem is that you are modifying the address held in the variable ptr.

You call AllocMem to allocate a buffer, which you refer to using ptr. That much is fine. But you must never change the value of ptr, the address of the buffer. And you do change it.

You wrote:

ptr:=AllocMem(40);
ptr:=Pchar('OneNationUnderGod');

The second line is the problem. You have modified ptr and now ptr refers to something else (a string literal held in read-only memory as it happens). You have now lost track of the buffer allocated by your call to AllocMem. You asked AllocMem for a new block of memory and then immediately discarded that block of memory.

What you presumably mean to do is to copy the string. Perhaps like this:

ptr := AllocMem(40);
StrCopy(ptr, 'OneNationUnderGod');

Now we are fine to call FreeMem, because ptr still contains the address that the call to AllocMem provided.

ptr := AllocMem(40);
try
  StrCpy(ptr, 'OneNationUnderGod');
  // do stuff with ptr
finally
  FreeMem(ptr);
end;

Clearly in real code you would find a better and more robust way to specify buffer lengths than a hard-coded value.


In your code, assuming the above fix is applied, the test for ptr being nil is needless. AllocMem never returns nil. Failure of AllocMem results in an exception being raised.


Having said all that, it's not usual to operate on string buffers in this way. It is normal to use Delphi strings. If you need a PChar, for instance to use with interop, make one with PChar(str) where str is of type string.

You say that you must use dynamically allocated PChar buffers. Perhaps that is so, but I very much doubt it.

Upvotes: 6

Arioch &#39;The
Arioch &#39;The

Reputation: 16045

I'd try to make what you've done more explicit. You seem to mistake the name of a variable with its value. However actually - considering values - what you did was

 ptrA:=AllocMem(40);
 ptrB:=Pchar('OneNationUnderGod');
 if ptrB<>nil then 
     FreeMem(ptrB);

Every new assignment changes the value overwriting the previous one, thus you freeing another pointer that was allocated.

You may read documentation for functions like StrNew, StrDispose, StrCopy, StrLCopy and sample codes with those to see some patterns of working with PChar strings.

Upvotes: 2

Remy Lebeau
Remy Lebeau

Reputation: 595295

It crashes because you are freeing static memory that was not dynamically allocated. There is no need to free memory used by literals at all. Only free memory that is dynamically allocated.

Upvotes: 2

Related Questions