Страница 1 из 1

Брутальный heap trace: узнай, какая сволочь запорола кучу

СообщениеДобавлено: 10.07.2014 10:31:59
Cheb
- Замедляет работу программы страшно (я об эффективности этой приблуды особо не заботился)
- Это *сырец* который будет ещё допиливаться (в тестовом примере не выдаются номера строк, только голые адреса, lineinfo не работает почему-то)
- НЕ совместимо с многими алгоритмами (мне пришлось в одном месте один парсинг переделывать чтобы работал дважды: на первом проходе выяснялось число элементов, а на втором - заполнялся массив. Иначе SetLength(x, Length(x) + 1) моментально съедали 800 мегабайт)

Но оно работает, :twisted: и номера строк отображаются в моём игровом движке (далеко не для всех адресов, блджад! :evil: ), что уже позволило выгрести два куска *страшного* говнокода, от которого всё падало (в частности, шла работа с уничтоженным экземпляром класса).

Принципы
- Блоки памяти и информация об аллокации хранятся раздельно, на растоянии в несколько сот мегабайт. Запарывание кучи не убьёт сам менеджер памяти.
- Вокруг блоков оставляются широкие поля, заполненные $55.
- Освобождённые блоки памяти на самом деле никуда не освобождаются, а хранятся вечно, с бектрейсом кто освободил и контрольной суммой. Если у вас идёт добавление к массиву по элементику - исчерпание памяти гарантировано.
- любые некорректные операции с памятью обнаруживаются и подробно журналятся
- периодически, при выходе или по команде выполняет проверку всех блоков памяти: не насрал ли кто на защитные поля, не изменилась ли контрольная сумма освобождённых блоков, и т.п.
- может затирать все освобождённые блоки памяти $55, чтобы программа громко падала при работе с ними.

Код: Выделить всё
Cheb's Brutal Heap Tracer started.
A change in a DEALLOCATED memory block detected
  Before:
     $0040B018 (no debug info: doesn't include this address range) in D:\chentrah\chentrah.exe
     $0040A19A (no debug info: doesn't include this address range) in D:\chentrah\chentrah.exe
     $0040A7B8 (no debug info: doesn't include this address range) in D:\chentrah\chentrah.exe
     $00450AE0, line 457 of \cl_main.inc in D:\chentrah\chentrah.exe
     $0045040F, line 380 of \cl_main.inc in D:\chentrah\chentrah.exe
     $0040191D, line 99 of \chentrah.lpr in D:\chentrah\chentrah.exe
     $0040EAD1 (no debug info: doesn't include this address range) in D:\chentrah\chentrah.exe
  After:
     $0040B018 (no debug info: doesn't include this address range) in D:\chentrah\chentrah.exe
     $00453944, line 119 of \cl_log.inc in D:\chentrah\chentrah.exe
     $004233AC, line 787 of \cge.pp in D:\chentrah\chentrah.exe
     $00450AB7, line 454 of \cl_main.inc in D:\chentrah\chentrah.exe
     $0045040F, line 380 of \cl_main.inc in D:\chentrah\chentrah.exe
     $0040191D, line 99 of \chentrah.lpr in D:\chentrah\chentrah.exe
     $0040EAD1 (no debug info: doesn't include this address range) in D:\chentrah\chentrah.exe
Memory block #128140:
  Size: 80
  Allocated by:
     $0040AFE2 (no debug info: doesn't include this address range) in D:\chentrah\chentrah.exe
     $0044FBE8, line 240 of \cl_main.inc in D:\chentrah\chentrah.exe
     $0040191D, line 99 of \chentrah.lpr in D:\chentrah\chentrah.exe
     $0040EAD1 (no debug info: doesn't include this address range) in D:\chentrah\chentrah.exe
  Freed by:
     $0040B018 (no debug info: doesn't include this address range) in D:\chentrah\chentrah.exe
     $00408A92 (no debug info: doesn't include this address range) in D:\chentrah\chentrah.exe
     $0045040F, line 380 of \cl_main.inc in D:\chentrah\chentrah.exe
     $0040191D, line 99 of \chentrah.lpr in D:\chentrah\chentrah.exe
     $0040EAD1 (no debug info: doesn't include this address range) in D:\chentrah\chentrah.exe
     $0040B018 (no debug info: doesn't include this address range) in D:\chentrah\chentrah.exe
     $0040A19A (no debug info: doesn't include this address range) in D:\chentrah\chentrah.exe
     $0040A7B8 (no debug info: doesn't include this address range) in D:\chentrah\chentrah.exe
     $00450AE0, line 457 of \cl_main.inc in D:\chentrah\chentrah.exe
     $0045040F, line 380 of \cl_main.inc in D:\chentrah\chentrah.exe
     $0040191D, line 99 of \chentrah.lpr in D:\chentrah\chentrah.exe
     $0040EAD1 (no debug info: doesn't include this address range) in D:\chentrah\chentrah.exe

Re: Брутальный heap trace: узнай, какая сволочь запорола куч

СообщениеДобавлено: 10.07.2014 11:17:27
runewalsh
Ты ведь знал про heaptrc, правда?

При одновременных аллокациях из разных потоков очень быстро падает в случайном месте, в том числе на минимальном примере.
Код: Выделить всё
{$mode objfpc}

uses chebs_heap_brutal_trace;

  function AllocationThread(param: pointer): PtrInt;
  const
    BlockSize: array[0 .. 5] of SizeUint = (5, 10, 20, 50, 100, 5000);
  var
    blocks: array[0 .. 20000] of pointer;
    i: integer;
  begin
    for i := 0 to High(blocks) do
      blocks[i] := GetMem(BlockSize[i mod length(BlockSize)]);

    for i := 0 to High(blocks) do
      FreeMem(blocks[i]);
    result := pPtrInt(@param)^;
  end;

var
  tA, tB: TThreadID;

begin
  tA := BeginThread(@AllocationThread, nil);
  tB := BeginThread(@AllocationThread, nil);
  WaitForThreadTerminate(tA, 0);
  WaitForThreadTerminate(tB, 0);
  writeln('OK');
end.

Попробуй использовать свою TRTLCriticalSection вместо NeedLock. Из одного тоже падает, но уже в Ran out of memory pool после чуть меньше 200K аллокаций. (Такое количество аллокаций само по себе неправильно, — кстати, да, надо бы оптимизировать у себя это дело :D, — но падать-то зачем?)

Re: Брутальный heap trace: узнай, какая сволочь запорола куч

СообщениеДобавлено: 10.07.2014 12:29:08
Cheb
heaptrc недостаточно брутален :evil:
- он хранит кусок памяти и описание вместе. Запороть - как два пальца об асфальт. А в таких случаях ответ на вопрос "где" важнее самого факта.
- он не умеет проверять после *каждой* операции. Только при завершении программы. А мой даёт четыре бектрейса: выделение, освобождение, и две проверки, между которыми произошла порча кучи.
- при изменении размера он действительно пытается изменить размер, мой же всегда делает Freeze + Alloc, позволяя всегда поймать обращение по указателю, протухшему в результате реаллокации

Добавлено спустя 4 минуты 8 секунд:
Re: Брутальный heap trace: узнай, какая сволочь запорола кучу
Попробуй использовать свою TRTLCriticalSection вместо NeedLock.

Вот же, же... Вечером переделаю.

но падать-то зачем?

А блоки никогда не освобожадаются :twisted: Память вышла - дальнейшая работа невозможна. Он не использует стандартный аллокатор вообще, кроме первого раза, когда берёт непрерывный кусок в 500 мегабайт.

Re: Брутальный heap trace: узнай, какая сволочь запорола куч

СообщениеДобавлено: 25.10.2014 11:47:25
zohaa3492
се в одном большом юните?
Действительно, ну её нафиг, эту модульность.:)