Конференция "Сети" » Проблема с освобождением памяти в сокетах [WinXP]
 
  • DmitryA (24.02.11 14:09) [0]
    Есть такая процедура:
    procedure Check();
    var Socket: TSocket;
    begin
    Socket := WinSock.socket(PF_INET, SOCK_STREAM, 0);

    WinSock.shutdown(Socket, SD_BOTH);

    WinSock.closesocket(Socket);
    end;

    осуществляем проверку и вызываем ее 1000 раз:
    for Index := 1 to 1000 do Check();

    получаем утечку памяти на 142-152 KB за проверку. Т.е. 10 проверок = 10000 вызовов Check = 1.5 MB.

    Кто-нибудь знает как устранить это явление?
  • xmen (24.02.11 14:38) [1]
    что-то не ясно как из этого кода определили утечку?
  • DmitryA (24.02.11 14:45) [2]
    Диспетчер задач Windows и TaskInfo. Программа имеет только этот код, так что никаких дополнительных операций нет
  • DmitryA (24.02.11 14:48) [3]
    В дополнение. Это код у клента. К серверу коннектится. И вопрос к утечке памяти у клиента
  • han_malign (24.02.11 15:29) [4]
    MSDN: closesocked(SOCKET) finction [Winsock]
      ...
    Here is a summary of closesocket behavior:

    If SO_DONTLINGER is enabled (the default setting) it always returns immediately???connection is gracefully closed in the background.

    If SO_LINGER is enabled with a zero time-out:
    – it always returns immediately — connection is reset/terminated.

    If SO_LINGER is enabled with a nonzero time-out:
    – with a blocking socket, it blocks until all data sent or time-out expires.
    – with a nonblocking socket, it returns immediately indicating failure.

    - реже долбиться надо...
  • DmitryA (24.02.11 17:48) [5]
    Спасибо!
    Буду пробовать...
  • DmitryA (24.02.11 19:16) [6]
    НЕ РАБОТАЕТ!
    1) добавил после создания сокета
    Linger.l_onoff  := 0;
    Linger.l_linger := 0;
    WinSock.setsockopt(Socket, SOL_SOCKET, SO_LINGER, PAnsiChar(@Linger), SizeOf(Linger));
    Значение опции устанавливается, но результат тот же

    2) -"-
    Linger.l_onoff  := 0;
    Linger.l_linger := 0;
    WinSock.setsockopt(Socket, SOL_SOCKET, SO_DONTLINGER, PAnsiChar(@Linger), SizeOf(Linger)); // возвращает ошибку WSAENOPROTOOPT
  • DmitryA (24.02.11 19:42) [7]
    К стати, чтобы "реже долбиться", следал задержку после закрытия сокета на 100 мсек. Эффект - тот же :(
  • sniknik © (25.02.11 08:08) [8]
    память выделенная программе <> потерянная (утечка)
    выделяется чаще из "чистой" области, так проще и быстрее, что и является главной целью, а не минимизация в отображении диспетчере задач. отдается не сразу, а по запросу, или если нет свободной в запросе на выделение.
    чтобы сравнивать нужно "добиться" перераспределения памяти, с очисткой уже свободной но еще не отданной в "общий пул", например свернув программу в панель задач (в этот момент делается как бы "уборка программы на хранение" с перераспределением памяти), ну или выполняя функцию которой это делается там.

    p.s. в инете куча статей типа "почему не нужно смотреть память в диспетчере задачь"
  • DmitryA (25.02.11 12:10) [9]
    Прикол состоит в том, что это все "от лукавого". Я смотрю по TaskInfo, это указано выше. Я это использовал всегда - вопросов не было. Проект, в котором это используется - старый и огромный (исходных текстов на 50МБ), и там, все остальное, корректно байт в байт.
  • Сергей М. © (25.02.11 12:35) [10]
    > получаем утечку памяти на 142-152 KB за проверку

    У меня нет никаких утечек - ни за одну "проверку", ни даже за один проход цикла

    Да, есть прирост воркингсета на 16 кб за 1-й же проход цикла.
    Те же 16 кб прироста фигурируют  при любом кол-ве "проверок".

    И это совершенно нормально и никакой "утечкой" не является.

    http://zalil.ru/30567596

    program Job;

    {$APPTYPE CONSOLE}

    uses
     CRT, Winsock;

    procedure Check();
    var
     Socket: TSocket;
    begin
     Socket := WinSock.socket(PF_INET, SOCK_STREAM, 0);
     WinSock.shutdown(Socket, SD_BOTH);
     WinSock.closesocket(Socket);
    end;

    var
     i: Integer;
    begin
     // скриншот До.jpg
     for i := 1 to 1000 do Check;
     // скриншот После.jpg
     ReadKey;
    end.



    Что я неправильно делаю ?)
  • DmitryA (25.02.11 13:12) [11]
    Повторил Ваш пример. У меня TaskInfo и TaskManager показывают одинаково - до 1716КБ до и 1728 КБ после.

    Для цикла в 10000, данные такие: до 1716КБ до и 1728 КБ после.
    Прироста нет. :) Но мой тест ранее был в GUI. Один и тот жет тест в GUI и консоле дает разные результаты. :) Проверю еще...

    К стати, здесь shutdown вызывать не нужно, т.к. еще нет соединения и вызов не отрабаотывается и возврашает SOCKET_ERROR.
  • Сергей М. © (25.02.11 13:18) [12]
    > Один и тот жет тест в GUI и консоле дает разные результаты

    Какие бы ни давал, но к утечкам в Winsock (по кр.мере применительно к тестируемой логике) он не имеет ни малейшего отношения.
  • DmitryA (26.02.11 13:29) [13]
    В Вашем примере сокет вообще не создается (Socket = -1) - не инициализорована библиотека сокетов. Поэтому и нет никакой утечки.

    Попробуйте так:
    program Project1;

    {$APPTYPE CONSOLE}

    uses
    SysUtils, WinSock;

    procedure Check();
    var voSocket: TSocket;
    begin
    voSocket := WinSock.socket(PF_INET, SOCK_STREAM, 0);

    WinSock.closesocket(voSocket);
    end;

    var voWSAData: TWSAData;
       viIndex: integer;
    begin
    WSAStartup($0201, voWSAData);

    ReadLn;

    for viIndex := 1 to 1000 do Check();

    ReadLn;

    WSACleanup();
    end.

  • sniknik © (26.02.11 15:15) [14]
    > Попробуйте так:
    запускаю,  занято памяти в таск менеджере = 1744 байт
    неактуально (см [8])
    делаю сворачивание/разворачивание программки = 92 байта... берем за точку отсчета
    нажимаю ентер в программе (первый "ридлайн") = 1036 байт
    неактуально (см [8])
    сворачивание/разворачивание = 92 байта...
    ???
    вы про какую утечку?
  • sniknik © (26.02.11 15:26) [15]
    пробуй,
    хотя процедура чуть не так работает как сворачивание (не полностью), видать еще нужно не просто убрать неиспользуемое с конца, но и перераспределить чтобы убрать фрагментацию в использованном.
    ну, да все одно показатель.

    program Project1;

    {$APPTYPE CONSOLE}

    uses
     Windows,
     SysUtils,
     WinSock;

    procedure Check();
    var voSocket: TSocket;
    begin
    voSocket := WinSock.socket(PF_INET, SOCK_STREAM, 0);

    WinSock.closesocket(voSocket);
    end;

    var
     voWSAData: TWSAData;
     viIndex: integer;
    begin
     WSAStartup($0201, voWSAData);
     SetProcessWorkingSetSize(GetCurrentProcess, dword(-1), dword(-1));
     ReadLn;

     for viIndex := 1 to 1000 do Check();

     SetProcessWorkingSetSize(GetCurrentProcess, dword(-1), dword(-1));
     ReadLn;

     WSACleanup();
    end.



    p.s. кстати не советую применять функцию в реальных программах, для "минимизации памяти", только тормозов добавишь, если например не кстати, случайно попадет в цикл/пересекеться с менеджером памяти.
  • Сергей М. © (26.02.11 23:04) [16]

    > DmitryA   (26.02.11 13:29) [13]
    >
    > В Вашем примере сокет вообще не создается


    Процедуру чека я содрал один в один из твоего 1-го поста, там где собственно и зашла речь об утечке
  • xmen (27.02.11 00:01) [17]

    > DmitryA   (24.02.11 14:45) [2]
    >
    > Диспетчер задач Windows и TaskInfo. Программа имеет только
    > этот код, так что никаких дополнительных операций нет


    ну дык это не говорит об утечке, не так ли?

    по идее нужно определить количество выделенной и освобожденной памяти, чтобы выяснить если ли утечка.

    менеджер памяти запускает сборщик мусора, после чего память освобожденная в программе, должна стать доступна другим программам.

    Как вариант можно попробовать запустить другую программу выделяющую большое количество памяти, и посмотреть уменьшился ли объем выделенной памяти в первой программе.
  • sniknik © (27.02.11 01:16) [18]
    > менеджер памяти запускает сборщик мусора
    это в дельфе то?

    > Как вариант можно попробовать запустить другую программу ...
    товарищ писатель, может, как вариант, попробуешь почитать ветку? где уже все объяснено и даны методы более очевидные и наглядные чем тот бред который вы предлагаете.
  • xmen (27.02.11 17:34) [19]

    > sniknik ©   (27.02.11 01:16) [18]

    А ты мне номер телефона оставь, я буду звонить тебе и спрашивать как поступить!
 
Конференция "Сети" » Проблема с освобождением памяти в сокетах [WinXP]
Есть новые Нет новых   [134436   +26][b:0.001][p:0.001]