Возникло необработанное исключение std::bad_alloc

Нужно написать простой графический редактор, в котором есть кисть, ластик и возможность сохранять файл в формате bmp.

#include <iostream>
#include <wingdi.h>

// Константы для определения типов инструментов
const int TOOL_PENCIL = 0;
const int TOOL_BRUSH = 1;
const int TOOL_ERASER = 2;
HBRUSH hBrush = CreateSolidBrush(RGB(0, 0, 0));
bool isDrawing = false;
POINT prevPoint;

void SaveImageToFile(HBITMAP hBitmap, const char* filename) {
    BITMAP bmp;
    GetObject(hBitmap, sizeof(BITMAP), &bmp);

    BITMAPFILEHEADER bmfh = { 0 };
    bmfh.bfType = 0x4D42; // "BM" magic number
    bmfh.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + bmp.bmWidth * bmp.bmHeight * 4;
    bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

    BITMAPINFOHEADER bmih = { 0 };
    bmih.biSize = sizeof(BITMAPINFOHEADER);
    bmih.biWidth = bmp.bmWidth;
    bmih.biHeight = bmp.bmHeight;
    bmih.biPlanes = 1;
    bmih.biBitCount = 32;
    bmih.biCompression = BI_RGB;

    FILE* file;
    errno_t err = fopen_s(&file, filename, "wb");
    if (err == 0 && file) {
        fwrite(&bmfh, sizeof(BITMAPFILEHEADER), 1, file);
        fwrite(&bmih, sizeof(BITMAPINFOHEADER), 1, file);

        HDC hdc = GetDC(NULL);
        HDC memDC = CreateCompatibleDC(hdc);

        HBITMAP oldBmp = (HBITMAP)SelectObject(memDC, hBitmap);

        BITMAPINFO bmi = { 0 };
        bmi.bmiHeader = bmih;

        GetDIBits(memDC, hBitmap, 0, bmp.bmHeight, NULL, &bmi, DIB_RGB_COLORS);

        BYTE* bits = new BYTE[bmp.bmWidth * bmp.bmHeight * 4];
        GetDIBits(memDC, hBitmap, 0, bmp.bmHeight, bits, &bmi, DIB_RGB_COLORS);

        fwrite(bits, bmp.bmWidth * bmp.bmHeight * 4, 1, file);

        delete[] bits;

        SelectObject(memDC, oldBmp);
        DeleteDC(memDC);
        ReleaseDC(NULL, hdc);

        fclose(file);
    }
    else {
        std::cout << "Error saving image" << std::endl;
    }
}

void CleanupResources(HWND hWnd, HBITMAP hBitmap) {
    if (hBitmap) {
        DeleteObject(hBitmap);
    }
    HDC hdc = GetDC(hWnd);
    ReleaseDC(hWnd, hdc);
}

// Класс для рисования инструментов
class CPaintTool {
public:
    virtual void Draw(HDC hdc, POINT prevPoint, POINT currentPoint) = 0;
};

// Класс для карандаша
class CPencil : public CPaintTool {
public:
    void Draw(HDC hdc, POINT prevPoint, POINT currentPoint) override {
        MoveToEx(hdc, prevPoint.x, prevPoint.y, NULL);
        LineTo(hdc, currentPoint.x, currentPoint.y);
    }
};

// Класс для кисти
class CBrush : public CPaintTool {
public:
    void Draw(HDC hdc, POINT prevPoint, POINT currentPoint) override {
        Ellipse(hdc, currentPoint.x - 5, currentPoint.y - 5, currentPoint.x + 5, currentPoint.y + 5);
    }
};

// Класс для ластика
class CEraser : public CPaintTool {
public:
    void Draw(HDC hdc, POINT prevPoint, POINT currentPoint) override {
        SelectObject(hdc, GetStockObject(WHITE_PEN));
        MoveToEx(hdc, prevPoint.x, prevPoint.y, NULL);
        LineTo(hdc, currentPoint.x, currentPoint.y);
        SelectObject(hdc, GetStockObject(BLACK_PEN));
    }
};

// Класс графического редактора
class CGraphicEditor {
public:
    CGraphicEditor() : m_hWnd(NULL), m_hdc(NULL), m_selectedTool(nullptr), m_previousPoint({ 0, 0 }) {}

    void Initialize(HWND hWnd) {
        m_hWnd = hWnd;
        m_hdc = GetDC(hWnd);
    }

    void SetTool(CPaintTool* tool) {
        m_selectedTool = tool;
    }

    void Draw(POINT currentPoint) {
        if (m_selectedTool) {
            m_selectedTool->Draw(m_hdc, m_previousPoint, currentPoint);
            m_previousPoint = currentPoint;
        }
    }

private:
    HWND m_hWnd;
    HDC m_hdc;
    CPaintTool* m_selectedTool;
    POINT m_previousPoint;
};

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    static CGraphicEditor graphicEditor;
    static CPencil pencil;
    static CBrush brush;
    static CEraser eraser;
    static HBITMAP hBitmap;

    switch (message) {
    case WM_CREATE:
        graphicEditor.Initialize(hWnd);
        return 0;

    case WM_MOUSEMOVE: {
        POINTS points = MAKEPOINTS(lParam);
        POINT currentPoint = { points.x, points.y };
        graphicEditor.Draw(currentPoint);
        if (isDrawing) {
            HDC hdc = GetDC(hWnd);
            SelectObject(hdc, hBrush);
            POINT currentPoint;
            currentPoint.x = LOWORD(lParam);
            currentPoint.y = HIWORD(lParam);
            MoveToEx(hdc, prevPoint.x, prevPoint.y, NULL);
            LineTo(hdc, currentPoint.x, currentPoint.y);
            prevPoint = currentPoint;
            ReleaseDC(hWnd, hdc);
        }
        return 0;
    }

    case WM_LBUTTONDOWN: {
        int tool = TOOL_PENCIL; // Выбираем инструмент (карандаш, кисть, ластик)
        switch (tool) {
        case TOOL_PENCIL:
            graphicEditor.SetTool(&pencil);
            break;
        case TOOL_BRUSH:
            graphicEditor.SetTool(&brush);
            break;
        case TOOL_ERASER:
            graphicEditor.SetTool(&eraser);
            break;
        }
        SetCapture(hWnd); // Захватываем мышь для отслеживания движения за пределами окна
        return 0;
    }

    case WM_LBUTTONUP:
        isDrawing = false;
        return 0;

    //case WM_KEYDOWN:
       // if (wParam == 'S') {
            //const wchar_t* wideString = L"image.bmp";
           // int size_needed = WideCharToMultiByte(CP_ACP, 0, wideString, -1, NULL, 0, NULL, NULL);
           // char* filename = new char[size_needed];
           // WideCharToMultiByte(CP_ACP, 0, wideString, -1, filename, size_needed, NULL, NULL);

           // graphicEditor.SaveImageToFile(hBitmap, filename);
           // delete[] filename;
       // }
        //return 0;

    //case WM_KEYDOWN:
        //if (wParam == 'S') {
            //const wchar_t* wideString = L"image.bmp";
            //int size_needed = WideCharToMultiByte(CP_ACP, 0, wideString, -1, NULL, 0, NULL, NULL);
            //char* filename = new char[size_needed];
            //WideCharToMultiByte(CP_ACP, 0, wideString, -1, filename, size_needed, NULL, NULL);

           // SaveImageToFile(hBitmap, filename);
            //delete[] filename;
        //}
       // return 0;

    case WM_KEYDOWN:
        if (wParam == 'S') {
            const wchar_t* wideString = L"image.bmp";
            char filename[MAX_PATH];
            if (WideCharToMultiByte(CP_ACP, 0, wideString, -1, filename, MAX_PATH, nullptr, nullptr) != 0) {
                SaveImageToFile(hBitmap, filename);
            }
            else {
                // Обработка ошибки при преобразовании
                MessageBox(nullptr, "Ошибка при преобразовании строки.", "Ошибка", MB_OK | MB_ICONERROR);
            }
        }
        return 0;

    case WM_PAINT: {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hWnd, &ps);
        FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
        EndPaint(hWnd, &ps);
        return 0;
    }

    case WM_DESTROY:
        CleanupResources(hWnd, hBitmap);
        PostQuitMessage(0);
        PostQuitMessage(0);
        return 0;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
};

int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow) {
    WNDCLASS wc = { 0 };
    wc.lpfnWndProc = WndProc;
    wc.hInstance = hInstance;
    wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND);
    wc.lpszClassName = "SimplePaint";

    if (!RegisterClass(&wc))
        return 1;

    HWND hWnd = CreateWindow(
        wc.lpszClassName,
        TEXT("Simple Paint"), // или L"Simple Paint"
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 800, 600,
        NULL,
        NULL,
        hInstance,
        NULL
    );
    if (!hWnd)
        return 1;

    ShowWindow(hWnd, nCmdShow);

    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

Имею следующую проблему: Вызвано исключение по адресу 0x00007FFFD0D25B0C: исключение Microsoft C++: std::bad_alloc по адресу памяти 0x00000073F4EFF070. Возникло необработанное исключение по адресу 0x00007FFFD0D25B0C: исключение Microsoft C++: std::bad_alloc по адресу памяти 0x00000073F4EFF070.

Возникает она, когда я нажимаю клавишу "S" для сохранения. Пробовала по разному фиксить - не выходит. Что делать с проблемой?


Ответы (0 шт):