На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! user posted image
Пожалуйста, выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.

Соблюдайте общие правила форума

Следующие вопросы задаются очень часто, подробно разобраны в FAQ и, поэтому, будут безжалостно удаляться:
1. Преобразовать переменную типа String в тип PChar (PAnsiChar)
2. Как "свернуть" программу в трей.
3. Как "скрыться" от Ctrl + Alt + Del (заблокировать их и т.п.)
4. Как запустить программу/файл? (и дождаться ее завершения)
5. Как перехватить API-функции, поставить hook? (перехват сообщений от мыши, клавиатуры - внедрение в удаленное адресное прстранство)
... (продолжение следует) ...

Внимание:
Попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка - 60 дней. Последующие попытки - бан.
Мат в разделе - бан на три месяца...

Полезные ссылки:
user posted image MSDN Library user posted image FAQ раздела user posted image Поиск по разделу user posted image Как правильно задавать вопросы


Выразить свое отношение к модераторам раздела можно здесь: user posted image Rouse_, user posted image Krid

Модераторы: Rouse_, Krid
  
> Какой аналог MemAvail в Delphi
    Если мы добавляем элемент в список, то проверяем сколько есть в Heap if memavail<SizeOf(нужный элемент) then exit;
    Как такое можно реализовать в Delphi?
      Это реальная проблема с которой вы столкнулись или переделывается 16 битная программа с TP/Delphi1 или Вы только пересели на Дельфи из какой-то 16ти битной среды программирования?
        Ну, ты загнул, конечно это реальная проблема!
        Вообще-то я не то написал MaxAvail надо было!
        Вот это все как? Мне вообщем функция, которая говорит сколько место в heap:

        Status.dwMemoryLoad: Количество используемой памяти в процентах (%).
        Status.dwTotalPhys: Общее количество физической памяти в байтах.
        Status.dwAvailPhys: Количество оставшейся физической памяти в байтах.
        Status.dwTotalPageFile: Объём страничного файла в байтах.
        Status.dwAvailPageFile: Свободного места в страничном файле.
        Status.dwTotalVirtual: Общий объём виртуальной памяти в байтах.
        Status.dwAvailVirtual: Количество свободной виртуальной памяти в байтах.
        Сообщение отредактировано: javas -
          Цитата
          javas, 15.12.03, 17:34
          Вообще-то я не то написал MaxAvail надо было!


          MaxAvail пишиться очень просто. Вот так:


          function MaxAvail:integer;
          begin
            Result:=4*1024*1024*1024; //4 гига.
          end;

            Цитата
            Fantasist, 18.12.03, 03:37
            MaxAvail пишиться очень просто. Вот так:

            function MaxAvail:integer;
            begin
              Result:=4*1024*1024*1024; //4 гига.
            end;


            Во первых, при компиляции такого ты получишь Overflow in conversion or arithmetic operation.
            Во вторых, могут столько и не дать, если места на диске мало smile.gif.

            А если серьезно, то с точностью до байта, как в старом недобром DOS'е давал MaxAvail, под виндами получить невозможно - система многозадачная, в ней все постоянно живет, меняется. Т.е. если даже предположить наличие такой функции, то между моментом ее вызова и моментом вызова функции запроса памяти, другой нехороший процесс может сожрать всю обещаную Вам память.

            Под виндами, как и в других многозадачных системах, обычно используется другая стратегия:
            Вы просто запрашиваете необходимый Вам объем памяти, а потом смотрите дали Вам ее или нет.
              ОК, понятно! biggrin.gif
                Цитата
                Петрович, 19.12.03, 03:18
                Во вторых, могут столько и не дать, если места на диске мало
                Такого никогда не дадут smile.gif В Win32 под приложение отводится 2ГБ(если хорошо попросить, то 3ГБ), реально немного меньше.
                Цитата
                Петрович, 19.12.03, 03:18
                А если серьезно, то с точностью до байта, как в старом недобром DOS'е давал MaxAvail, под виндами получить невозможно
                А как же GetHeapStatus?
                Цитата
                Петрович, 19.12.03, 03:18
                Т.е. если даже предположить наличие такой функции, то между моментом ее вызова и моментом вызова функции запроса памяти, другой нехороший процесс может сожрать всю обещаную Вам память.
                У каждого процесса своя виртуальная память, так что про другие процессы с определенными ограничениями можно забыть. smile.gif
                  Цитата
                  trainer, 20.12.03, 13:33
                  Такого никогда не дадут  В Win32 под приложение отводится 2ГБ(если хорошо попросить, то 3ГБ), реально немного меньше.

                  Сначала хотел ответить так-же, но решил сначала сам проверить. Так вот, 3 с лишним Гб дали легко!.
                  Цитата
                  trainer, 20.12.03, 13:33
                  А как же GetHeapStatus?

                  Дак как я и сказал - скажут что есть, а потом могут недать.
                  Цитата
                  trainer, 20.12.03, 13:33
                  У каждого процесса своя виртуальная память, так что про другие процессы с определенными ограничениями можно забыть.

                  Так-то оно так. Но, во первых, в рамках своего процесса порой работают и потоки и модули о которых мало что известно (COM-объекты, Dll, и т.п.), а они тоже памяти хотят, причем именно памяти твоего процесса. А во вторых, да, другие процессы имеют свою виртуальную память. Но надо понимать что ВСЯ виртуальная память отображается на единственную физическую память и HDD. Поэтому, все процессы черпают ее из одной кастрюльки, увы не бесконечной smile.gif.
                    Цитата
                    Петрович, 20.12.03, 09:17
                    Сначала хотел ответить так-же, но решил сначала сам проверить. Так вот, 3 с лишним Гб дали легко!.



                    А какая винда? Есть предположение что этакие штуки только в 2000/XP проходят, а в более древних виндах всё те же 2Gb...
                      Цитата (Петрович @ 20.12.03, 17:17)
                      Сначала хотел ответить так-же, но решил сначала сам проверить. Так вот, 3 с лишним Гб дали легко!.

                      Приведи код вызова и как ты определял.
                        Цитата
                        Петрович, 20.12.03, 17:17
                        Так вот, 3 с лишним Гб дали легко!.
                        Если верить Джеффри Рихтеру, а не верить ему нет оснований, такое должно быть только в линейке WinNT для 64-разрядных процессоров(IA-64,Alpha). Там приложению отведено 4 ТБ.
                        Так что если это 32-разрядная версия Windows, то любопытно посмотреть на код.
                          Господа. Приношу свои извинения за ошибочные сведения которые я привел в своем сообщении №8 ph34r.gif - Сильно не бейте smile.gif.
                          Теперь подробнее.
                          Когда я писал о выполненной мной проверке, я имел в виду следующий код:
                          procedure TestGetMem;
                          const Size :Cardinal = 3*Cardinal(1024*1024*1024);
                          var   p    :PChar;
                          begin
                            try
                              GetMem(p,Size);
                              try
                                FillChar(p^,Size,0);
                                Windows.MessageBox(GetActiveWindow,'Ok','',0);
                              finally
                                FreeMem(p);
                              end;
                            except on e:Exception do
                              Windows.MessageBox(GetActiveWindow,PChar('Error:'+e.Message),'',0);
                            end;
                          end;

                          Замечу, что код выполняется без Exception, из чего я и сделал предположение что мне дали запрошенные 3Гб. Иначе, было-бы Exception, в соответствии с описанием на Delphi 6:
                          If there isn't enough memory available to allocate the dynamic variable, an EOutOfMemory exception is raised.

                          Вот отсюда и неверность моего ответа (причем я сам был удивлен).

                          Теперь, я решил более подробно исследовать вопрос. Вот код который я написал:
                          procedure TestGetMem;

                            procedure Test (s :String; Size :Cardinal);
                            var p :PChar;
                            begin
                              try
                                GetMem(p,Size);
                                if  p = nil  then
                                  Log(s+' - Nil !')
                                else begin
                                  Log(s+' - Ok');
                                  FreeMem(p);
                                end;
                              except on e:Exception do
                                Log(s+' - Exception: '+e.Message);
                              end;
                            end;

                          const
                            Mb = Cardinal(1024*1024);
                            Gb = Cardinal(1024*1024*1024);
                          begin
                            Test('3 Gb         ',3*Gb          );
                            Test('2 Gb         ',2*Gb          );
                            Test('2*Gb - 1b    ',2*Gb - 1      );
                            Test('2*Gb - 10b   ',2*Gb - 10     );
                            Test('1*Gb + 150*Mb',1*Gb + 150*Mb );
                          end;

                          После его запуска я получил результат еще больше удививший меня blink.gif :
                          3 Gb          - Nil !
                          2 Gb          - Nil !
                          2*Gb - 1b     - Exception: Не хватает памяти
                          2*Gb - 10b    - Exception: Нарушение доступа по адресу 00401D5E в модуле 'Project1.exe'. Запись по адресу 8099BFFC
                          1*Gb + 150*Mb - Ok

                          Особое удивление вызывает 4-я строка (2*Gb-10b). Хотя строки 1 и 2 тоже вызывают привычное ощущение - опять обманули (см. цитату из справки).
                          Вот и все, выводы можете делать сами.
                          Да, забыл уточнить. Ипытание проводиолсь в среде Delphi 6 под Windows XP.
                          И еще, если кто захочет попробовать, Log - это моя функция, аналогом может быть что-то вроде:
                          procedure Log (s :String);
                          begin
                            Form1.Memo.Lines.Add(s);
                          end;
                          Сообщение отредактировано: Петрович -
                            Тут возникает такой вопрос, если я динамически создаю список, например, диспечер показывает, что размер виртуальной памяти для приложения был 2024, запускаю создание списка и вижу, что размер доходит до 30000 потом снижается до 19000, т.е. почему за моим приложением осталось лишнее место, если я его не использую ohmy.gif, при повторном создании 19000 увеличивается, т.е. это значит утечка есть dry.gif

                            Как ее выявить и избежать?
                            Сообщение отредактировано: javas -
                              Может утечка, а может и особенности распределителя памяти Delphi.
                              По поводу обнаружения утечек. Есть модуль MemCheck позволяющий обнаруживать утечки. См. здесь
                                Все в порядке, размер получается как до, так и после тем же! Просто отлично, но
                                может я чего не понял, как этот юнит работает, просто он вылетает на строчке

                                mov eax, [ebp + 12]
                                в функции

                                function ltgmCallerIsNewAnsiString: boolean;
                                 //Tells if the guy who called GetMem is NewAnsiString

                                после

                                IntToStr(Beg^.Adr1.LtCurrent.Age);

                                И на всех таких с функцией IntToStr(), и говорит, что все равно есть утечка, хоть диспечер и показывает, что вроде все нормально!

                                Ошибка:Access violation at adress...
                                Сообщение отредактировано: javas -
                                  Цитата
                                  javas, 24.12.03, 02:48
                                  может я чего не понял, как этот юнит работает, просто он вылетает на строчке

                                  У меня (Delphi 6) MemCheck прекрасно работает.

                                  Для правильного использования этого модуля необходимо сделать следующее:

                                  1. Вставить ссылку на модуль MemCkeck в список используемых модулей в файле проекта (.dpr);
                                  2. Вставить вызов процедуры MemChk после begin в файле проекта (.dpr);
                                  3. Выполнить следующие настройки в Project Options:
                                  Compiler/Optimization - выключить
                                  Compiler/Stack frames - включить
                                  Compiler/Debugging - включить все в этой группе (Use Debug DCUs не обязательно, но желательно)
                                  Linker/Include TD32 debug info - включить
                                  Packages/Runtime packages/Build with runtime packages - выключить

                                  Например, сделал следующий проект:
                                  program Project1;
                                  uses
                                    MemCheck, // <---## Добавил ручками
                                    Forms,
                                    Unit1 in 'Unit1.pas' {fmTestDA};

                                  {$R *.res}

                                  begin
                                    MemChk;   // <---## Добавил ручками
                                    Application.Initialize;
                                    Application.CreateForm(TForm1, Form1);
                                    Application.Run;
                                  end.

                                  Соответственно на Form1 пара кнопок со следующими обработчиками:
                                  procedure TForm1.Button1Click(Sender: TObject);
                                  var p :PChar;
                                  begin
                                    GetMem(p,100);
                                  end;

                                  procedure TForm1.Button2Click(Sender: TObject);
                                  var p :tStringList;
                                  begin
                                    p := tStringList.Create;
                                  end;

                                  Теперь запускаю. Если не нажимать никаких кнопок, то после завершения программы появляется файл Project1_MemCheck.log содержащий:
                                  MemCheck version 2.67

                                  Total leak: 0 bytes


                                  *** MEMCHK: Blocks STILL allocated ***

                                  *** MEMCHK: End of allocated blocks ***


                                  *** MEMCHK: Chronological leak information ***


                                  *** MEMCHK: End of chronological leak information ***


                                  *** MEMCHK: Blocks written to after destruction ***

                                   Bad blocks count: 0


                                  *** MEMCHK: End of blocks written to after destruction ***

                                  Если-же нажать сначала Button1 а затем Button2, то после завершения файл Project1_MemCheck.log содержит:
                                  MemCheck version 2.67

                                  Total leak: 148 bytes


                                  *** MEMCHK: Blocks STILL allocated ***

                                  Leak #0 Instance of TStringList
                                   Size: 48
                                   1 Occurence
                                   call stack - 0 : Module Unit1.pas Routine @Unit1@TForm1@Button2Click Line 54 Find error: 005009D0
                                   call stack - 1 : Module Controls.pas Routine @Controls@TControl@Click Line 4621 Find error: 0045247C
                                   call stack - 2 : Module StdCtrls.pas Routine @Stdctrls@TButton@Click Line 3347 Find error: 0043FCC4
                                   call stack - 3 : Module StdCtrls.pas Routine @Stdctrls@TButton@CNCommand Line 3399 Find error: 0043FE2B
                                   call stack - 4 : Module Controls.pas Routine @Controls@TControl@WndProc Line 4561 Find error: 0045224E
                                   call stack - 5 : Module Controls.pas Routine @Controls@TWinControl@WndProc Line 6242 Find error: 00455D1B
                                   call stack - 6 : Module StdCtrls.pas Routine @Stdctrls@TButtonControl@WndProc Line 3327 Find error: 0043FC0F
                                   call stack - 7 : Module Controls.pas Routine @Controls@TControl@Perform Line 4468 Find error: 00451F59
                                   call stack - 8 : Module Controls.pas Routine @Controls@DoControlMsg Line 6288 Find error: 00455EDD
                                   call stack - 9 : Module Controls.pas Routine @Controls@TWinControl@WMCommand Line 6474 Find error: 004566BA
                                   call stack - 10 : Module Controls.pas Routine @Controls@TControl@WndProc Line 4561 Find error: 0045224E
                                   call stack - 11 : Module Controls.pas Routine @Controls@TWinControl@WndProc Line 6242 Find error: 00455D1B
                                   call stack - 12 : Module Controls.pas Routine @Controls@TWinControl@MainWndProc Line 6139 Find error: 004558EB
                                   call stack - 13 : Module classes.pas Routine @Classes@StdWndProc Line 10562 Find error: 0042B9A6
                                   call stack - 14 : (no debug info) Find error: 77D57B13
                                   call stack - 15 : (no debug info) Find error: 77D5CDCA
                                   call stack - 16 : (no debug info) Find error: 77D34599
                                   call stack - 17 : (no debug info) Find error: 77D347B0
                                   call stack - 18 : (no debug info) Find error: 77F5108B
                                   call stack - 19 : (no debug info) Find error: 77D361F2
                                   call stack - 20 : (no debug info) Find error: 77D4EBFE
                                   call stack - 21 : (no debug info) Find error: 77D4C3F2
                                   call stack - 22 : (no debug info) Find error: 77D57B13
                                   call stack - 23 : (no debug info) Find error: 77D5CDCA
                                   call stack - 24 : (no debug info) Find error: 77D35CC5
                                   call stack - 25 : (no debug info) Find error: 77D35CE4
                                   call stack - 26 : Module Controls.pas Routine @Controls@TWinControl@DefaultHandler Line 6269 Find error: 00455E61

                                  Leak #1 User allocated memory (GetMem)
                                   Size: 100
                                   1 Occurence
                                   call stack - 0 : Module Unit1.pas Routine @Unit1@TForm1@Button1Click Line 47 Find error: 005009AE
                                   call stack - 1 : Module Controls.pas Routine @Controls@TControl@Click Line 4621 Find error: 0045247C
                                   call stack - 2 : Module StdCtrls.pas Routine @Stdctrls@TButton@Click Line 3347 Find error: 0043FCC4
                                   call stack - 3 : Module StdCtrls.pas Routine @Stdctrls@TButton@CNCommand Line 3399 Find error: 0043FE2B
                                   call stack - 4 : Module Controls.pas Routine @Controls@TControl@WndProc Line 4561 Find error: 0045224E
                                   call stack - 5 : Module Controls.pas Routine @Controls@TWinControl@WndProc Line 6242 Find error: 00455D1B
                                   call stack - 6 : Module StdCtrls.pas Routine @Stdctrls@TButtonControl@WndProc Line 3327 Find error: 0043FC0F
                                   call stack - 7 : Module Controls.pas Routine @Controls@TControl@Perform Line 4468 Find error: 00451F59
                                   call stack - 8 : Module Controls.pas Routine @Controls@DoControlMsg Line 6288 Find error: 00455EDD
                                   call stack - 9 : Module Controls.pas Routine @Controls@TWinControl@WMCommand Line 6474 Find error: 004566BA
                                   call stack - 10 : Module Controls.pas Routine @Controls@TControl@WndProc Line 4561 Find error: 0045224E
                                   call stack - 11 : Module Controls.pas Routine @Controls@TWinControl@WndProc Line 6242 Find error: 00455D1B
                                   call stack - 12 : Module Controls.pas Routine @Controls@TWinControl@MainWndProc Line 6139 Find error: 004558EB
                                   call stack - 13 : Module classes.pas Routine @Classes@StdWndProc Line 10562 Find error: 0042B9A6
                                   call stack - 14 : (no debug info) Find error: 77D57B13
                                   call stack - 15 : (no debug info) Find error: 77D5CDCA
                                   call stack - 16 : (no debug info) Find error: 77D34599
                                   call stack - 17 : (no debug info) Find error: 77D347B0
                                   call stack - 18 : (no debug info) Find error: 77F5108B
                                   call stack - 19 : (no debug info) Find error: 77D361F2
                                   call stack - 20 : (no debug info) Find error: 77D4EBFE
                                   call stack - 21 : (no debug info) Find error: 77D4C3F2
                                   call stack - 22 : (no debug info) Find error: 77D57B13
                                   call stack - 23 : (no debug info) Find error: 77D5CDCA
                                   call stack - 24 : (no debug info) Find error: 77D35CC5
                                   call stack - 25 : (no debug info) Find error: 77D35CE4
                                   call stack - 26 : Module Controls.pas Routine @Controls@TWinControl@DefaultHandler Line 6269 Find error: 00455E61

                                  *** MEMCHK: End of allocated blocks ***


                                  *** MEMCHK: Chronological leak information ***

                                  * User allocated memory (GetMem) (Leak #1) Size: 100
                                  * Instance of TStringList (Leak #0) Size: 48

                                  *** MEMCHK: End of chronological leak information ***


                                  *** MEMCHK: Blocks written to after destruction ***

                                   Bad blocks count: 0


                                  *** MEMCHK: End of blocks written to after destruction ***



                                  Вот так.
                                  Сообщение отредактировано: Петрович -
                                  0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                  0 пользователей:


                                  Рейтинг@Mail.ru
                                  [ Script execution time: 0,0409 ]   [ 16 queries used ]   [ Generated: 27.04.24, 08:49 GMT ]