尝试在 C 中复制 4 个字符结构的二维数组时出现 memcpy 错误分段错误

memcpy error segmentation fault while trying to copy 2D array of 4 char structure in C

嘿,我正在尝试复制从另一个图像创建的 SDL_Color 数组。但是对于某些图像,我得到:

Process finished with exit code -1073741819 (0xC0000005)

它发生在 20 x 20 像素的图像上,但它适用于 50 x 50 的图像... 这是我的代码:

FILE *debugFile = fopen("C:\Users\Clement\Documents\coding\ImageOfCLife\debug.txt", "w+");
int imgWidth, imgHeight, channels;
unsigned char *img = stbi_load("C:\Users\Clement\Documents\coding\ImageOfCLife\star.jpg", &imgWidth,
                               &imgHeight, &channels, 0);
fprintf(debugFile, "Loaded image with a width of %dpx, a imgHeight of %dpx and %d channels\n", imgWidth, imgHeight, channels);
dRulesLen = sizeof(deathRules);
bRulesLen = sizeof(birthRules);
if (img == NULL) {
    fprintf(debugFile, "Error in loading the image\n");
    exit(3);
}

int ch, pix;
SDL_Color **stateMatrix1 = (SDL_Color **) malloc(imgHeight * sizeof(SDL_Color*));
if (stateMatrix1 == NULL) {
    fprintf(debugFile,"Unable to allocate memory\n");
    exit(1);
}
for (int i = 0; i < imgHeight; ++i) {
    stateMatrix1[i] = (SDL_Color *) malloc(imgWidth * sizeof(SDL_Color));
}
for (ch = 0; ch < imgHeight; ch++) {
    printf("{");
    for (pix = 0; pix < imgWidth; pix++) {
        unsigned bytePerSDL_Color = channels;
        unsigned char *SDL_ColorOffset = img + (pix + imgHeight * ch) * bytePerSDL_Color;
        SDL_Color p = initSDL_Color(SDL_ColorOffset);
        stateMatrix1[ch][pix] = p;
        printSDL_Color(p);
        printf(", ");
    }
    printf("}\n");
}
SDL_Color stateMatrix2[imgHeight][imgWidth];
memcpy(stateMatrix2, stateMatrix1, imgWidth*imgHeight*sizeof(SDL_Color)); 

最后一行是根据the debugger的问题 我试过了

memcpy(stateMatrix2, stateMatrix1, sizeof(stateMatrix2))

也是,但我得到了相同的结果。

我与 minGW 和 Clion 合作 windows 10。希望你能帮我解决这个问题。

我还尝试用 :

替换 SDL_Color stateMatrix2[imgHeight][imgWidth];
    SDL_Color **stateMatrix2 = (SDL_Color **) malloc(imgHeight * sizeof(SDL_Color*));
if (stateMatrix2 == NULL) {
    fprintf(debugFile,"Unable to allocate memory\n");
    exit(1);
}
for (int i = 0; i < imgHeight; ++i) {
    stateMatrix2[i] = (SDL_Color *) malloc(imgWidth * sizeof(SDL_Color));
}

但我遇到了同样的问题。

我忘了说了,但我希望 ant 能够同时使用 stateMatrix 作为函数的参数。

为了修复它,我使用了下面解释的 Olaf 解决方案: 我保留了:

SDL_Color **stateMatrix1 = (SDL_Color **) malloc(imgHeight * sizeof(SDL_Color*));
if (stateMatrix1 == NULL) {
    fprintf(debugFile,"Unable to allocate memory\n");
    exit(1);
}
for (int i = 0; i < imgHeight; ++i) {
    stateMatrix1[i] = (SDL_Color *) malloc(imgWidth * sizeof(SDL_Color));
}

为矩阵分配内存并使用:

for (int i = 0; i < imgHeight; ++i) {
memcpy(stateMatrix2[i], stateMatrix1[i], imgWidth * sizeof(SDL_Color));
}

执行复制。 我也验证了两个矩阵没有关联,没有问题。

您的错误已在评论中解释。您可以通过为矩阵分配一个连续的内存块而不是像您那样分配许多块来修复它。这种方法更简单,用于分配、释放和复制(因为您可以使用对 memcpy 的单个调用):

#include <stdio.h>
#include <stdlib.h>

struct SDL_Color {
    unsigned char rgba[4];
};

int main() {
    int ch, pix;
    int imgWidth = 100;
    int imgHeight = 100;
    struct SDL_Color (*stateMatrix1)[imgWidth][imgHeight] = malloc(sizeof(*stateMatrix1));
    if (*stateMatrix1 == NULL) {
        printf("Unable to allocate memory\n");
    } else {
        free(*stateMatrix1);
        printf("Success\n");
    }
    return 0;
}

您只需要在每次使用矩阵时取消对矩阵的指针的引用即可。

复制时

memcpy(stateMatrix2, stateMatrix1, imgWidth * imgHeight * sizeof(SDL_Color));

您将超越 stateMatrix1 的结尾,这不是 imgWidth * imgHeight * sizeof(SDL_Color),而是 imgHeight * sizeof(SDL_Color*)


stateMatrix1 循环复制到 stateMatrix2 是解决此问题的一种方法

for (int i = 0; i < imgHeight; ++i) {
    memcpy(stateMatrix2[i], stateMatrix1[i], imgWidth * sizeof(SDL_Color));
}

另一种方法是使两个矩阵成为同一类型。但是当分配 stateMatrix2

SDL_Color **stateMatrix2 = (SDL_Color **) malloc(imgHeight * sizeof(SDL_Color*));

以后使用和上面一样的memcpy,你仍然会超越stateMatrix1 and 现在也超越了stateMatrix2 .


正确的复制方式(但由于其他原因仍然是错误的)是

memcpy(stateMatrix2, stateMatrix1, sizeof(*stateMatrix1));

这在大小上是正确的,但仍然是错误的,因为它将 stateMatrix1 指针 复制到 stateMatrix2。这有两个作用

  1. 当你用自己的指针初始化stateMatrix2时,会出现内存泄漏。
  2. 现在两个矩阵都指向同一个内存,这意味着改变一个,也会改变另一个。