1. Pascal / Говнокод #16191

    +86

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    function IsMemoryCommitByAdress(const AAddress: Pointer): Boolean;
    var
      MemoryInfo: TMemoryBasicInformation;
    begin
      Result := False;
      if not Assigned(AAddress) then
      Exit;
      VirtualQuery(AAddress, MemoryInfo, SizeOf(MemoryInfo));
      Result := MemoryInfo.State and MEM_COMMIT <> 0;
    end;
    
    function IsPointerToVMT(const APointer: Pointer): Boolean;
      var
      VMTPointer, VMTPointerSelf: Pointer;
    begin
      Result := False;
      if not IsMemoryCommitByAdress(APointer) then
      Exit;
      VMTPointer := APointer;
      VMTPointerSelf := Pointer(Integer(VMTPointer) + vmtSelfPtr);
      if not IsMemoryCommitByAdress(VMTPointer) then
      Exit;
      if not IsMemoryCommitByAdress(VMTPointerSelf) then
      Exit;
      if not IsMemoryCommitByAdress(PPointer(VMTPointerSelf)^) then
      Exit;
      Result := PPointer(VMTPointerSelf)^ = VMTPointer;
    end;
    
    function IsBadptr(apointer:pointer):boolean;
    begin
      Result := IsMemoryCommitByAdress(APointer) and IsPointerToVMT(PPointer(APointer)^);
    end;

    Функция, для определения качества указателя, в ситуации "один объект - несколько указателей".
    Гк в том, что нет надежности - это все равно, что юзать IsBadReadPtr и аналогичные.

    Почему-то никто не пытается использовать операторы is и as (я узнал о них благодаря Тарасу, спасибо ему), чтобы сравнить качество приведения.

    Запостил: brutushafens, 19 Июня 2014

    Комментарии (19) RSS

    • Это актуально во всяких отладчиках, артманиях, ботах и тд
      Ответить
      • Ну т.е. для копания в чужих процессах. В своём то нахера такое счастье?
        Ответить
    • > определения качества указателя
      А не проще не ложить в указатели мусор и не забывать занилять их, есил память освободили?

      > is и as
      is и as запросто могут крашнуться на мусорном указателе. Разве нет?
      Ответить
      • Мне казалось, что много где и много что может крашнуться, если попытается что-то сделать с памятью по мусорному указателю.
        Ответить
        • Угу. Поэтому правильное решение только одно - не допускать мусорных указателей.
          Ответить
          • А для надежность использовать код выше, который не даст нам крашнутся даже если они появятся
            Ответить
    • >Почему-то никто не пытается использовать операторы is и as (я узнал о них благодаря Тарасу, спасибо ему), чтобы сравнить качество приведения.
      И как по-твоему работает is?
      Точно также, он обращается к указателю как к объекту и пытается прочитать по отрицательному смещению указатель на vmt.
      Только я сомневаюсь что он проверяет выделена ли данная память (в fpc не проверяет), соответственно если вместо указателя передали случайное число, то программа с "is" крашнется, а эта процедура вернет false.

      ---
      Вот краш: http://ideone.com/jAE6Oq
      Ответить
      • cleaned
        Ответить
        • А дальше....
          writeln( TObject(23) is TObject);

          получаем Runtime Error. Потому что обратились по некорректному адресу.
          Ответить
          • cleaned
            Ответить
            • > А что делать, если в поток передали указатель на объект, но при этом сам объект удалили посреди выполнения потока?
              Как я и писал выше - просто никогда так не делать. Заранее продумай, кто будет отвечать за жизнь объекта и как эта ответственность будет передаваться, и проблемы не будет. Ну либо реализуй/найди потокобезопасный подсчет ссылок, раз уж сборщика мусора нету в делфи.

              А as и is совсем не для этого придуманы. Они нужны на случай, если ты указатель на какой-нибудь TStringList кастанул в TObject и хочешь проверить - а правда ли это не просто TObject, а именно TStringList. Ну и кастануть в обратную сторону... Для мусорных указателей они совершенно не предназначены, это UB, как любят говорить крестовики.
              Ответить
              • cleaned
                Ответить
                • > item с извлеченным устройством будет убран из списка
                  Ну как вариант - просто помечай их каким-нибудь флагом вместо удаления. Либо отдавай объекты потокам насовсем, а поток при завершении пусть втыкает результаты в какойнить потокобезопасный список.

                  Ну либо отдавай потоку не объект а какой-нибудь идентификатор (раз объект все равно не юзаешь). И если item'а с таким идентификатором нет - просто забивай на результат.

                  Либо перед удалением айтема сначала останови соотв. поток.

                  Вариантов дохера, на самом деле ;)
                  Ответить
              • >Ну и кастануть в обратную сторону...

                dynamic_cast в Дельфи? Нахрен им это говно сдалось? Лучше так ничего и не придумали?
                Ответить
    • Vanished
      Ответить

    Добавить комментарий