Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

memory leak using primitives #1515

Open
jarroddavis68 opened this issue Nov 27, 2023 · 6 comments
Open

memory leak using primitives #1515

jarroddavis68 opened this issue Nov 27, 2023 · 6 comments

Comments

@jarroddavis68
Copy link

Hi, I hooked Allegro memory allocation to Delphi and discovered a small memory leak using primitives. Here is the code:

var
  MemInterface: ALLEGRO_MEMORY_INTERFACE;
  mem: TDictionary<Pointer, NativeUInt>;

procedure initmem;
begin
  mem := TDictionary<Pointer, NativeUInt>.Create;
end;

procedure donemem;
var
  item: TPair<Pointer, NativeUint>;
begin
  writeln('Dangling allocations: ', mem.Count);

  for item in mem do
  begin
    FreeMem(item.Key);
    WriteLn('Size: ', item.Value, ' bytes');
  end;

  mem.Free;
end;

function MyMalloc(size: NativeUInt; line: Integer; const file_: PAnsiChar; const func: PAnsiChar): Pointer; cdecl;
begin
  Result := AllocMem(size);
  mem.Add(Result, size);
end;

procedure MyFree(ptr: Pointer; line: Integer; const file_: PAnsiChar; const func: PAnsiChar); cdecl;
begin
  mem.Remove(ptr);
  FreeMem(ptr);
end;

function MyRealloc(ptr: Pointer; size: NativeUInt; line: Integer; const file_: PAnsiChar; const func: PAnsiChar): Pointer; cdecl;
begin
  mem.Remove(ptr);
  Result := ReallocMemory(ptr, size);
  mem.Add(Result, size);
end;

function MyCalloc(n: NativeUInt; size: NativeUInt; line: Integer; const file_: PAnsiChar; const func: PAnsiChar): Pointer; cdecl;
begin
  Result := AllocMem(n * size);
  mem.Add(Result, n * size);
end;

procedure Test01();
var
  display: PALLEGRO_DISPLAY;
begin
  if al_install_system(ALLEGRO_VERSION_INT, nil) then
  begin
    al_init_primitives_addon();
    al_set_new_window_title('Allegro');
    al_set_new_display_flags(Ord(ALLEGRO_OPENGL_3_0));
    display := al_create_display(640, 480);
    al_draw_filled_rectangle(0, 0, 100, 100,al_map_rgba(255, 0, 0, 255));
    al_destroy_display(display);
    al_uninstall_system();
  end;
end;

begin
  initmem();
  // Setting up the memory interface with custom functions
  MemInterface.mi_malloc := MyMalloc;
  MemInterface.mi_free := MyFree;
  MemInterface.mi_realloc := MyRealloc;
  MemInterface.mi_calloc := MyCalloc;

  // Apply the custom memory interface to Allegro
  al_set_memory_interface(@MemInterface);

  Test01();

  donemem();
end.

The call to donemem will report and clean up any leaked memory. Test01 is the smallest example to trigger the leak. If you comment out the call the al_draw_filled_rectangle, there will be no leak. Even in a loop, multiple calls to different primiatives, there is only 1 allocation, 56 bytes in size.

@ReiquelApplegate
Copy link
Contributor

The only function call in al_draw_filled_rectangle is to al_draw_prim.

@jarroddavis68
Copy link
Author

The only function call in al_draw_filled_rectangle is to al_draw_prim.

Nevertheless, memory seems to leak when a primitive routine is called. Comment out the call, no leak.

@ReiquelApplegate
Copy link
Contributor

What happens if you call:

al_free(target);

right before the return ret; in al_draw_prim? Does the leak go away?

@jarroddavis68
Copy link
Author

What happens if you call:

al_free(target);

right before the return ret; in al_draw_prim? Does the leak go away?

Hi, regrettably, due to the extended period without a response, I was compelled to switch to a different framework to meet a project deadline. My development environment relies heavily on Delphi, necessitating a complex process to compile C code into a DLL and then adapt the headers for Delphi's use. I hope to possibly reconsider allegro in the future.

I had thought about closing this issue earlier but decided against it, recognizing its validity and hoping it might eventually be acknowledged and resolved.

Thank you for your assistance. Currently, I don't have a setup available for testing. This issue was initially reported several months ago, and it's possible that it has since been resolved or perhaps worsened. However, the problem can be readily identified by monitoring allocations and deallocations, which do not align, pinpointing the core issue.

@SiegeLord
Copy link
Member

Why don't you test it, @ReiquelApplegate :)

@pedro-w
Copy link
Contributor

pedro-w commented Feb 20, 2024

I'm not sure this leak is something we should worry about, since it's small and does not appear to get any bigger with repeated use. I haven't got Windows but there are a few instances in the MacOS code that look like

allegro5/src/macosx/osxgl.m

Lines 2623 to 2632 in c4bc6dc

ALLEGRO_DISPLAY_INTERFACE* _al_osx_get_display_driver(void)
{
static ALLEGRO_DISPLAY_INTERFACE* vt = NULL;
if (vt == NULL) {
vt = al_malloc(sizeof(*vt));
memset(vt, 0, sizeof(ALLEGRO_DISPLAY_INTERFACE));
vt->create_display = create_display;
}
return vt;
}

For sure there is memory allocated to vt which isn't reclaimed, but it is never lost and it never increases.
I suspect this 56 bytes may be something like that.
It would be possible to confirm where it's coming from by making use of the line / file / func parameters to the custom allocation functions. (maybe the test code will have to be rewritten in C first if @jarroddavis68 isn't able to reproduce any more)
Hope that helps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants