views:

296

answers:

3

Hi all

I am trying to run a old midi component in Delphi, and it works for the most part of it, but if I try loading 2 files in a row, it crashes.

some research led me to install EurekaLog, which point to memory leaks in the code.yay!

I'm not very good with memory pointers stuff, but this code down is highlighted by Eureka here got me thinking, maybe there is a bug with memory not being freed??

I tried adding FreeMem at the end of it, but it doesn't work?

function TMidifile.ReadString(F: integer): string;
var
  s: PChar;
  i: integer;
begin
  GetMem(s, F + 1);
  s[F] := chr(0);
  for i := 0 to F - 1 do
  begin
    s[i] := Chr(chunkIndex^);
    inc(chunkIndex);
  end;
  result := string(s);
end;
A: 

The problem is that you can't take a bunch of random bytes and cast it as a string. string has a specific structure, and allocation is managed by the compiler.

I could rewrite this bit for you, but I don't think I'd be doing you any favors, since I must presume that the code which is calling this is not doing any better in terms of memory management.

Craig Stuntz
+1  A: 

You can't typecast to an AnsiString, for they are reference counted.

Wouldn't this be easier?

function TMidifile.ReadString(F: integer): string; 
var i: integer; 
begin
  SetLength(Result, F);  
  for i := 1 to F do 
  begin 
    Result[i] := Chr(chunkIndex^); 
    inc(chunkIndex); 
  end; 
end;
Kornel Kisielewicz
This appears to have solved the case! I ain't get no warnings of leaked memory anymore :)Thanks for the magical fix! **Testing under way**
Dom Soucy
@Dom: Great! Glad it helped :)
Kornel Kisielewicz
I never taught such a small part of code could fix it! i'm amazed
Dom Soucy
+3  A: 

Kornel's got the right idea. You could probably simplify it even further, like so:

function TMidifile.ReadString(F: integer): AnsiString; 
begin
  SetLength(Result, F);
  Move(ChunkIndex^, result[1], F);
  inc(chuncIndex, F);
end;

This will make reading a lot faster, especially if you're using the Fastcode version of Move (or a recent version of Delphi that comes with the Fastcode version built into the RTL.)

Mason Wheeler
+1: I didn't dare to do it the `move` way, for I don't have a compiler handy to test it ;>
Kornel Kisielewicz
@Mason: be careful, as Dom might be using Delphi 2009 or higher, and Move then moves bytes, not characters.
Jeroen Pluimers
Good point. Edited to take that into account.
Mason Wheeler
Tried your routine, but for some reasons it generated a Range CHeck Error. But thanks for the effort.
Dom Soucy
On which line? The only way I can think of that that would generate a range check error is on the second line (Move), if F = 0. If that's the case, then add in `if F = 0 then result := '' else ...` at the top of the function and it should take care of it.
Mason Wheeler
Yes I believe it's a F = 0 problem too. I got the same error trying another routine with i= 0 to F, but i:= 1 to F is ok.thanks!
Dom Soucy