Winsock, растет память...

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by Sifon110, 12 Apr 2014.

  1. Sifon110

    Sifon110 New Member

    Joined:
    13 Mar 2011
    Messages:
    34
    Likes Received:
    1
    Reputations:
    0
    Подскажите пожалуйста, в чем может быть проблема. Суть в том, что с каждым новым вызовом функции растет память на 4-12 кб и не особождается.

    Code:
    var
      err, er: integer;
      host, server, data: string;
      port: integer;
      addr: TSockAddr;
      block: bool;
      fds : TFDSet;
    begin
      err := 0;
      result := '';
    
      while err < Attempts do
      begin
          host := Pars('://', link, '/');
          if length(host) < 5 then
          begin
              result := 'request failed: link has incorrect format.';
              exit;
          end;
    
          sock := socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    
          server := host;
          port := 80;
    
          if length(server) < 8 then
          begin
              result := 'request failed.';
              exit;
          end
          else begin
              addr.sin_family := AF_Inet;
              addr.sin_port := htons(port);
              addr.sin_addr.S_addr := inet_addr(Pchar(server));
    
              block := true;
              ioctlsocket(sock, FIONBIO, cardinal(block));
    
              if Connect(sock, @addr, SizeOf(TSockAddrin)) = SOCKET_ERROR then
              begin
                  if WSAGetLastError = WSAEWOULDBLOCK then
                  begin
                      FD_ZERO(fds);
                      FD_SET(sock, fds);
                      er := select(0, nil, @fds, nil, @tv);
                  end;
              end;
    
              block := false;
              ioctlsocket(sock, FIONBIO, cardinal(block));
    
              if er < 1 then
              begin
                  inc(err);
              end
              else begin
    
                  if not method then
                  begin
                      data := 'GET ' + link + ' HTTP/1.1' + #13#10 +
                              'User-Agent: ' + useragent +  #13#10 +
                              'Host: ' + host + #13#10 +
                              'Accept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/webp, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1' + #13#10 +
                              'Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3' + #13#10 +
                              'Connection: close' + #13#10 +
                              #13#10;
                  end
                  else begin
                      data := 'POST ' + link + ' HTTP/1.1' + #13#10 +
                              'User-Agent: ' + useragent + #13#10 +
                              'Host: ' + host + #13#10 +
                              'Connection: Keep-Alive' + #13#10 +
                              'Content-Length: ' + inttostr(length(postdata)) + #13#10 +
                              'Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3' + #13#10 +
                              'Accept: application/json, text/javascript, */*; q=0.01' + #13#10 +
                              'X-Requested-With: XMLHttpRequest' + #13#10 +
                              'Content-Type: application/x-www-form-urlencoded' + #13#10 +
                              'Pragma: no-cache' + #13#10 +
                              'Cache-Control: no-cache' + #13#10 +
                              #13#10 +
                              postdata;
                  end;
    
                  send(sock, data[1], length(data), 0);
    
                  result := recvdata(sock, TimeoutOnRead);
    
                  if result = '' then
                      inc(err)
                  else begin
                      closesocket(sock);
                      break;
                  end;
              end;
    
          end;
    
          closesocket(sock);
      end;
    
      if err = Attempts then
          result := 'request failed';
    
    Code:
    function recvdata(sock : TSocket; sec : integer) : string;
    var
       tv : timeval;
       fds : TFDSet;
       buf : array [1..4096] of char;
       res : string;
       r : integer;
    begin
       result := '';
       r := 1;
       FD_ZERO(fds);
       FD_SET(sock, fds);
       tv.tv_sec := sec;
       tv.tv_usec := 0;
       res := '';
    
       while (r > 0) do
       begin
          if select(0, @fds, nil, nil, @tv) <= 0 then
              break;
          r := recv(sock, buf, 4096, 0);
          res := res + copy(buf, 1, r);
       end;
    
       result := res;
    end;
    
     
  2. #colorblind

    #colorblind Moderator

    Joined:
    31 Jan 2014
    Messages:
    637
    Likes Received:
    246
    Reputations:
    42
    Поскольку сокет ты закрываешь, то есть предположение что память растет из-за
    Code:
    fds : TFDSet;
    я правда понятия не имею что это :D
     
  3. alexey-m

    alexey-m Elder - Старейшина

    Joined:
    15 Jul 2009
    Messages:
    518
    Likes Received:
    100
    Reputations:
    37
    конструкции вида:
    Code:
    while true do begin
    
      hSock:= socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
      
      if (Length(host) < 8) then begin
        result := 'request failed.';
        exit;
      end else begin
        addr.sin_family := AF_Inet;
        ..........
      end;
      closesocket(hSock);
    end;
    
    правильнее было бы обернуть в try finally end иначе при выполнении условия (Length(host) < 8) управление будет передано к точке выхода, минуя закрытия сокета
    Code:
    while true do begin
    
      hSock:= socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
      if (hSock <> INVALID_SOCKET) then try
      
        if (Length(host) < 8) then begin
          result := 'request failed.';
          exit;
        end else begin
          addr.sin_family := AF_Inet;
          ..........
        end;
      finally
        closesocket(hSock);
      end;
    end;
     
    #3 alexey-m, 13 Apr 2014
    Last edited: 13 Apr 2014
  4. Sifon110

    Sifon110 New Member

    Joined:
    13 Mar 2011
    Messages:
    34
    Likes Received:
    1
    Reputations:
    0
    alexey-m, точно.. точно. Спасибо большое. Невнимателен был. В некоторых исключительных ситуациях сокет просто не закрывался..