使用指针设置类属性时出错

时间:2014-01-08 21:03:25

标签: c++ pointers

我在使用指针设置类属性时出现问题,这是我的代码:(此版本将编译,但您需要打开扫雷窗口。)

WindowObject.h:

#ifndef WINDOWOBJECT_H_INCLUDED
#define WINDOWOBJECT_H_INCLUDED

#include <windows.h>
#include <stdio.h>

class WindowObject
{
public:
    WindowObject();

    BYTE* getPixelMap() const;
    void setPixelMap(BYTE* bitPointer);
    void getPixelMap(HWND hwnd);
private:
    BYTE* mPixelMap;
};

#endif

WindowObject.cpp:

#include "WindowObject.h"

WindowObject::WindowObject()
{
}

BYTE* WindowObject::getPixelMap() const
{
    printf("getPixelMap: %d\n", mPixelMap[0]); // it crashes, bad pointer!!
    return mPixelMap;
}

void WindowObject::setPixelMap(BYTE *bitPointer)
{
    printf("setPixelMap 1: %d\n", bitPointer[0]); // It works!
    mPixelMap = bitPointer;
    printf("setPixelMap 2: %d\n", mPixelMap [0]); // Why does this works and getPixelMap doesn't???
}

void WindowObject::getPixelMap(HWND hwnd)
{   
    HDC hdcWindow, hdcMemDC = NULL;
    HBITMAP hbmScreen = NULL;
    BITMAP bmpScreen;

    // Retrieve the handle to a display device context for the client 
    // area of the window.
    hdcWindow = GetDC(hwnd);

    // Create a compatible DC which is used in a BitBlt from the window DC
    hdcMemDC = CreateCompatibleDC(hdcWindow);

    if(!hdcMemDC)
    {
        MessageBoxA(hwnd, "CreateCompatibleDC has failed", "Failed", MB_OK);
        goto done;
    }

    // Get the client area for size calculation
    RECT rcClient;
    GetClientRect(hwnd, &rcClient);

    // Create a compatible bitmap from the Window DC
    hbmScreen = CreateCompatibleBitmap(hdcWindow, rcClient.right-rcClient.left, rcClient.bottom-rcClient.top);

    if(!hbmScreen)
    {
        MessageBoxA(hwnd, "CreateCompatibleBitmap Failed", "Failed", MB_OK);
        goto done;
    }

    //Get the BITMAP from the HBITMAP
    GetObject(hbmScreen,sizeof(BITMAP),&bmpScreen);

    BITMAPFILEHEADER   bmfHeader;    
    BITMAPINFOHEADER   bi;
    BYTE* bitPointer;

    bi.biSize = sizeof(BITMAPINFOHEADER);    
    bi.biWidth = bmpScreen.bmWidth;    
    bi.biHeight = bmpScreen.bmHeight;  
    bi.biPlanes = 1;    
    bi.biBitCount = 32;    
    bi.biCompression = BI_RGB;    
    bi.biSizeImage = 0;  
    bi.biXPelsPerMeter = 0;    
    bi.biYPelsPerMeter = 0;    
    bi.biClrUsed = 0;    
    bi.biClrImportant = 0;

    // Create a device independent bitmap that so that we can write to it directly
    hbmScreen = CreateDIBSection(hdcMemDC, (BITMAPINFO *)&bi, DIB_RGB_COLORS, (void**)(&bitPointer), NULL, NULL);

    // Select the compatible bitmap into the compatible memory DC.
    SelectObject(hdcMemDC, hbmScreen);

    // Bit block transfer into our compatible memory DC.
    if ( !BitBlt(hdcMemDC, 0, 0, rcClient.right-rcClient.left, rcClient.bottom-rcClient.top, hdcWindow, 0, 0, SRCCOPY) )
    {
        MessageBox(hwnd, "BitBlt has failed", "Failed", MB_OK);
        goto done;
    }

    // Create PixelMap
    int width = (rcClient.right-rcClient.left),
        height = (rcClient.bottom-rcClient.top);

    printf("Inside getPixelMap: %d\n", bitPointer[0]); // it works!
    setPixelMap(bitPointer);

done:
    DeleteObject(hbmScreen);
    DeleteObject(hdcMemDC);
    ReleaseDC(hwnd, hdcWindow);
}

main.cpp中:

#include "WindowObject.h"

int main()
{
    WindowObject wObj;
    HWND hwnd;

    hwnd = FindWindow(NULL, "Minesweeper");

    if (hwnd)
    {
        wObj.getPixelMap(hwnd);
        BYTE* bPointer = wObj.getPixelMap();
        printf("After getPixelMap: %d", bPointer[0]);
    }
}

程序崩溃了,它给了我一个“访问冲突读取位置”。我几乎100%确定问题来自我的指针,但我发现它在我的测试的每个阶段都有效,除非我用我的getPixelMap方法得到它。任何帮助将不胜感激!

2 个答案:

答案 0 :(得分:1)

问题是这个数据成员要么没有初始化(如果类的对象是默认初始化的),要么是值0.因此使用成员函数getPixelMap()是不安全的。另外,我认为函数setPixelMap的参数的生命可能小于类的对象的生命。所以程序的行为是不确定的。

我认为最好使用智能指针或分配内存供数据成员自己使用。

答案 1 :(得分:0)

在函数getPixelMap(HWND hwnd)中,在保存指针之后但在返回之前,您在返回的位图上调用DeleteObject。因此,当您稍后访问位图时,它不再是有效指针,因为根据CreateDIBSection文档,它表示在调用DeleteObject时将取消分配位图。

您需要保留位图对象(hbmScreen)并稍后将其删除,可能在析构函数中。