You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CreateDIBSection返回NULL的原因排查求助

问题根源分析

导致CreateDIBSection返回NULL且GetLastError返回0的原因有以下几点:

  • BITMAPINFO结构未正确初始化:代码修改了单独的BITMAPINFOHEADER变量,但从未将修改后的内容复制回传入CreateDIBSection的BITMAPINFO结构中。原始BITMAPINFO处于未初始化状态(包含垃圾数据),导致函数接收到无效参数。
  • biWidth值设置错误:biWidth被设为每行的字节数(步长),而非实际的像素宽度(408)。BITMAPINFOHEADER.biWidth字段要求的是像素宽度,不是字节数。
  • GetLastError调用时机错误:在调用CreateDIBSection后,代码先调用了calloc、sprintf、MessageBox等函数,这些函数会覆盖系统的错误码,导致最终GetLastError返回0而非CreateDIBSection的实际错误。
  • 未检查GetDC的返回值:GetDC可能返回NULL,但代码未处理这种情况,会导致后续CreateDIBSection调用失败。
修正后的代码
TRESULT GetDIBPage(_IN HWND inobj, _INOUT void **outobj){
    // Variable declarations
    void *tmpbits = NULL;
    char *tmpstr = NULL;
    BITMAPINFO tmpbmpinfo = {0}; // 初始化BITMAPINFO结构
    HDC tmphdc = NULL;
    HWND tmphndwindow = NULL;
    int pixel_width = 408; // 实际像素宽度
    int bytes_per_pixel = 3; // 24位色,每像素3字节
    int stride = 0;
    DWORD last_err = 0;
    HBITMAP hbmp = NULL;

    // Argument checks
    if(inobj == NULL || outobj == NULL){
        return TPTRISNULL;
    }

    // Initializations
    tmphndwindow = inobj;

    // 获取窗口设备上下文,并检查是否成功
    tmphdc = GetDC(tmphndwindow);
    if(tmphdc == NULL){
        MessageBox(NULL, "获取设备上下文失败", "错误", MB_OK);
        return TPTRISNULL;
    }

    // 计算步长(每行字节数,按4字节对齐)
    stride = pixel_width * bytes_per_pixel;
    if((stride % 4) != 0){
        stride = (stride + 3) & ~3; // 向上取整到4的倍数
    }

    // 设置BITMAPINFOHEADER字段
    tmpbmpinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    tmpbmpinfo.bmiHeader.biWidth = pixel_width; // 正确设置像素宽度
    tmpbmpinfo.bmiHeader.biHeight = 600;
    tmpbmpinfo.bmiHeader.biPlanes = 1;
    tmpbmpinfo.bmiHeader.biBitCount = 24;
    tmpbmpinfo.bmiHeader.biCompression = BI_RGB;
    tmpbmpinfo.bmiHeader.biSizeImage = stride * 600; // 步长 × 高度
    tmpbmpinfo.bmiHeader.biXPelsPerMeter = 0;
    tmpbmpinfo.bmiHeader.biYPelsPerMeter = 0;
    tmpbmpinfo.bmiHeader.biClrUsed = 0;
    tmpbmpinfo.bmiHeader.biClrImportant = 0;

    // 创建DIB Section,并立即获取错误码
    hbmp = CreateDIBSection(tmphdc, &tmpbmpinfo, DIB_RGB_COLORS, &tmpbits, NULL, 0);
    last_err = GetLastError();

    // 检查是否创建成功
    if(hbmp == NULL || tmpbits == NULL){
        tmpstr = (char*)calloc(513, sizeof(char));
        if(tmpstr != NULL){
            sprintf(tmpstr, "创建DIB失败。错误码:%lu", last_err);
            MessageBox(NULL, tmpstr, "错误", MB_OK);
            free(tmpstr);
        }
        ReleaseDC(tmphndwindow, tmphdc);
        return TPTRISNULL;
    }

    // 释放资源
    ReleaseDC(tmphndwindow, tmphdc);

    // 返回结果
    *outobj = tmpbits;
    return TSUCCESS;
}
关键修正点说明
  1. 正确初始化BITMAPINFO:使用={0}初始化BITMAPINFO结构,确保所有字段初始为0,然后直接设置bmiHeader的各个有效值,避免垃圾数据传入函数。
  2. 区分像素宽度和步长:将biWidth设为实际像素宽度408,单独计算步长(每行字节数)用于biSizeImage。
  3. 及时获取错误码:在CreateDIBSection调用后立即获取GetLastError,避免后续函数覆盖错误码。
  4. 增加GetDC错误检查:判断GetDC的返回值,若为NULL则直接返回错误。
  5. 检查CreateDIBSection的返回值:通过返回的HBITMAP句柄和tmpbits双重验证创建是否成功。

内容的提问来源于stack exchange,提问作者Thema Guishard

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 00:05:54