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

SDL2遍历像素数组触发0xC0000005错误,请求排查解决

问题:SDL遍历图像像素时触发0xC0000005内存访问错误

Process returned -1073741819 (0xC0000005)

尝试遍历图像像素修改颜色分量时反复出现上述错误,注释掉像素遍历循环后代码可正常运行,说明问题出在循环的像素访问逻辑中。

相关函数代码:

{
    SDL_Surface *retour = NULL;
    SDL_Color color = {255, 255, 255, 255};
    int i, j, w = (int) s->w, h = (int) s->h;
    Uint32 *src = NULL;
    if(SDL_LockSurface(s) < 0)
    {
        fprintf(stderr, "Erreur SDL_LockSurface : %s", SDL_GetError());
        goto lock_surface_fail;
    }
    src = (Uint32 *)s->pixels;

    for(i = 0; i < h; i++)
    {
        for(j = 0; j < w; j++)
        {
            SDL_GetRGB(src[i * w + j], s->format, &color.r, &color.g, &color.b);
            Uint8 gray = (color.r + color.g + color.b) / 3;
            src[i * w + j] = SDL_MapRGB(s->format, gray, gray, gray);
        }
    }
    printf("%d sur %d", w, h);
    retour = SDL_CreateRGBSurfaceWithFormatFrom(src, s->w, s->h, 32, s->pitch, s->format->format);
    if(NULL == retour)
    {
        fprintf(stderr, "Erreur SDL_CreateRGBSurface : %s",
                SDL_GetError());
    }

alloc_memory_fail:
    SDL_UnlockSurface(s);
lock_surface_fail:
    return retour;

}

出错的循环段:

for(i = 0; i < h; i++)
{
    for(j = 0; j < w; j++)
    {
        SDL_GetRGB(src[i * w + j], s->format, &color.r, &color.g, &color.b);
        Uint8 gray = (color.r + color.g + color.b) / 3;
        src[i * w + j] = SDL_MapRGB(s->format, gray, gray, gray);
    }
}

问题原因与修复方案

1. 核心问题:行偏移计算错误

SDL中SDL_Surface的pitch字段代表一行像素的总字节数,而非像素数量。由于内存对齐要求,pitch往往不等于w * 单个像素字节数。你直接用i * w计算行偏移,会导致内存越界访问,触发0xC0000005错误。

正确的行起始地址计算必须使用pitch:

Uint32 *row = (Uint32 *)((Uint8 *)src + i * s->pitch);

2. 次要问题:直接操作硬件表面风险

如果原Surface是硬件加速表面(比如从纹理导出的Surface),直接写入其pixels内存会触发访问违规。建议先创建一个可修改的软件Surface副本再操作。

修复后的完整代码

{
    SDL_Surface *retour = NULL;
    SDL_Color color = {255, 255, 255, 255};
    int i, j, w = (int)s->w, h = (int)s->h;
    Uint32 *src = NULL;

    // 创建可修改的软件Surface副本,避免操作硬件表面
    retour = SDL_CreateRGBSurfaceWithFormat(0, w, h, 32, s->format->format);
    if (!retour) {
        fprintf(stderr, "Erreur SDL_CreateRGBSurface : %s", SDL_GetError());
        goto lock_surface_fail;
    }
    SDL_BlitSurface(s, NULL, retour, NULL);

    if (SDL_LockSurface(retour) < 0) {
        fprintf(stderr, "Erreur SDL_LockSurface : %s", SDL_GetError());
        goto cleanup;
    }
    src = (Uint32 *)retour->pixels;

    for (i = 0; i < h; i++) {
        // 用pitch计算每行起始地址,避免越界
        Uint32 *row = (Uint32 *)((Uint8 *)src + i * retour->pitch);
        for (j = 0; j < w; j++) {
            SDL_GetRGB(row[j], retour->format, &color.r, &color.g, &color.b);
            // 加权计算灰度更符合人眼感知
            Uint8 gray = (Uint8)(0.299 * color.r + 0.587 * color.g + 0.114 * color.b);
            row[j] = SDL_MapRGB(retour->format, gray, gray, gray);
        }
    }

    SDL_UnlockSurface(retour);
    printf("%d sur %d", w, h);
    goto end;

cleanup:
    SDL_FreeSurface(retour);
    retour = NULL;
lock_surface_fail:
end:
    return retour;
}

额外优化提示

  • 灰度计算使用加权公式(0.299红 + 0.587绿 + 0.114蓝),比简单平均更符合人眼对色彩的感知。
  • 若原Surface像素格式不是32位,直接强制转换为Uint32*会导致错误,统一转换为32位软件Surface后处理更稳妥。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 06:33:19