Получая большой файл из памяти сокета, у меня есть утечка памяти? - PullRequest
0 голосов
/ 16 марта 2020

Я хочу отправить большой файл с одной машины на другую. Все байты отправлены успешно, и они также получены на другом конце, но операция массово попадает в память на принимающей стороне. Использование памяти увеличивается на 400 МБ в секунду в течение нескольких секунд, а затем уменьшается. Файл, который я тестировал, имеет размер около 7 гигов.

Это код, который я использую для чтения из сокета в файл:

size_t recv_file(int socket, std::filesystem::path& dest_file) {
    uint64_t bytes_to_read = recv_byte_count(socket);
    char* const file_buffer = new char[MAX_BUFFER_FILE];
    size_t total_received{ 0 };

    try {
        std::fstream fs;
        fs.open(dest_file, std::fstream::in | std::fstream::out | std::fstream::app);

        while (bytes_to_read > 0) {
            const unsigned int actual_bytes_to_read = (bytes_to_read > MAX_BUFFER_FILE) ? MAX_BUFFER_FILE : bytes_to_read;

            size_t received = recv_raw(socket, file_buffer, actual_bytes_to_read, MAX_BUFFER_FILE);

            if (received > 0) {
                fs.write(file_buffer, received);
                bytes_to_read -= received;
                total_received += received;
                std::cout << "Bytes received: " << total_received << std::endl;
                memset(file_buffer, 0, MAX_BUFFER_FILE);


            } else throw WSA_socket_exception(WSAGetLastError(), socket);

        }

        fs.close();
        delete[] file_buffer;
    }
    catch (...) {
        delete[] file_buffer;
        return 0;
    }
    return total_received;
}


size_t recv_raw(const int socket, void* buffer, size_t bytes_to_read, int buffer_size = MAX_BUFFER) {
    char* ptr = static_cast<char*>(buffer);
    size_t received_total{ 0 };

    while (bytes_to_read > 0) {
        const int actual_bytes_to_read{ std::min(buffer_size, static_cast<int>(bytes_to_read)) };

        const int received = recv(socket, ptr, actual_bytes_to_read, 0);
        if (received == 0 || received < -1) throw connection_close_exception(socket);
        if (received > 0) {
            bytes_to_read -= static_cast<size_t>(received);
            ptr += received;
            received_total += static_cast<size_t>(received);
        }
    }
    return received_total;
}

1 Ответ

1 голос
/ 16 марта 2020

Данные копируются много раз в течение процесса от получения до их окончательной записи в файл.

И tcp, и файл могут выделять много временных буферов, ожидающих либо полученного вызова, либо файла ( частично) сбрасывается в файловую систему. Tcp контролируется вашими настройками tcp, определяющими, сколько он может выделить, в fs может быть аналогичный параметр, иначе вы можете свернуть свой собственный, прокрутив свой собственный подкласс std :: streambuf. * ​​1003 *

...