c++gdi+winsock2win32guibad-alloc

C++ Code is throwing std::bad_alloc, i am trying to receive screenshots through socket and display to a gui window win32api


C++ Win32Api GUI, I Am trying to display received screenshots on server from client. I am trying to create a Remote Desktop Viewer. Client is capturing screenshots and then sending them to the server, where i am trying to receive and display to a window, but there are is a problem on which i am stuck at maybe a week. It is throwing std::bad_alloc when i received the image and try to add to memory on SERVER.(the screenshots are in jpeg format). Sometimes it throws std::bad_alloc instantly, but sometimes after received a few images.

Server.cpp {window procedure, the bad_alloc error is in WM_PAINT}:

    case WM_PAINT:
    {
        SOCKET selectedSocket = clientSockets[itemIndex];

        Sleep(1000 / 15);
        ULONGLONG bufferLenNetworkOrder = 0;
        int bytesReceived = 0;
        int rerr = 0;
        const int MAX_BYTES = 100000;
        while (bytesReceived < sizeof(bufferLenNetworkOrder)) {
            rerr = recv(selectedSocket, (char*)&bufferLenNetworkOrder + bytesReceived, sizeof(bufferLenNetworkOrder) - bytesReceived, 0);
            bytesReceived += rerr;
        }
        int bufferLen = ntohll(bufferLenNetworkOrder);

        imageBuffer.reset(new char[bufferLen]);
        bytesReceived = 0;

        while (bytesReceived < bufferLen && bufferLen < MAX_BYTES) {
            MessageBoxA(NULL, std::to_string(bufferLen - bytesReceived).c_str(), "CHECK", MB_OK);
            rerr = recv(selectedSocket, imageBuffer.get() + bytesReceived, bufferLen - bytesReceived, 0);
            if (rerr > 0 && rerr <= bufferLen - bytesReceived) {
                bytesReceived += rerr;
            }
            else {
                MessageBoxA(NULL, "ERROR", "CHECK", MB_OK);
                return {};
            }
        }

        if (bufferLen > MAX_BYTES)
        {
            return {};
        }

        HGLOBAL hGlobal = GlobalAlloc(GHND, bufferLen);
        void* pData = GlobalLock(hGlobal);
        memcpy(pData, imageBuffer.get(), bufferLen);

        GlobalUnlock(hGlobal);

        IStream* pStream = NULL;
        CreateStreamOnHGlobal(hGlobal, TRUE, &pStream);

        Gdiplus::Bitmap bitmap(pStream);
        Gdiplus::Status status = bitmap.GetLastStatus();


        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(Chwnd, &ps);

        int imgWidth = bitmap.GetWidth();
        int imgHeight = bitmap.GetHeight();

        Gdiplus::Graphics graphics(hdc);

        RECT clientRect;
        GetClientRect(Chwnd, &clientRect);

        graphics.DrawImage(&bitmap, 0, 0, imgWidth, imgHeight);
        GlobalFree(hGlobal);
        pStream->Release();
        imageBuffer.reset(new char[bufferLen]);
        EndPaint(Chwnd, &ps);
        
        break;
    }

Solution

  • I fixed it by checking if the bufferLen is not zero or less than zero in a do-while loop. Big thanks to drescherjm.