【问题标题】:Access violating reading when trying to deallocate a 2d array尝试释放二维数组时读取访问冲突
【发布时间】:2013-08-21 21:14:43
【问题描述】:

我正在尝试释放使用以下代码分配的第二个数组:

int** createMatrix(int k)
{
    int i;
    int **res;

    res = (int**)malloc(sizeof(int*)*k);
    checkalloc(res);

    for (i = 0; i < k; i++)
    {
        res[i] = (int*)malloc(sizeof(int)*k);
        checkalloc(res[i]);
    }
    return res;
}

具有以下功能

void freeMatrix(int ***matrix, int k)
{
    int i;

    for (i = 0; i < k; i++)
        free(matrix[i]);

    free(matrix);
}

第一个元素被很好地释放,但是当i=1 函数崩溃并出现错误:

First-chance exception at 0x0f7e7e2c (msvcr100d.dll) in Q2.exe: 0xC0000005: Access violation reading location 0xccccccc8.
Unhandled exception at 0x0f7e7e2c (msvcr100d.dll) in Q2.exe: 0xC0000005: Access violation reading location 0xccccccc8.

我做错了什么?

编辑:

尝试解除分配由以下人员分配的类似数组时,我也会遇到同样的情况:

CHARS** createImageMatrix(FILE *fp, int rows, int cols, int format)
{
    CHARS**res;
    int i;

    res = (CHARS**)malloc(sizeof(CHARS*)*rows);
    checkalloc(res);

    for (i = 0; i < height; i++)
    {
        res[i] = (CHARS*)malloc(sizeof(CHARS)*cols);
        checkalloc(res[i]);
    }
    return res;
}

并解除分配:

void freeCharsMatrix(CHARS **matrix, int rows)
{
    int i;
    for (i = 0; i < rows; i++)
        free(matrix[i]);
    free(matrix);
}

当 CHARS 为:

typedef struct Chars {
char A;
char B;
char C;
char D;

} 个字符;

但这次我明白了:

我怎么了?

【问题讨论】:

  • 您不必在 C 中强制转换 void* malloc 返回。
  • @hetepeperfan,这就是我需要分配内存的方式。这不是导致崩溃的原因。
  • 您分配了一个 int** 并随后释放了一个 int*** free_matrix
  • 通常情况下,three star programming 是不受欢迎的,或者它至少经常表明有问题或者可能有更好的方法来解决您的问题。
  • 如果您只是将返回值(来自createMatrix())传递给freeMatrix(),那么您应该已经从编译器收到了一个警告,即您错误地调用了freeMatrix() 函数。如果您将指针的地址传递给freeMatrix(),那么也许您应该在释放数据后将指针归零——并在freeMatrix() 中使用额外的间接级别。如果你有关于类型不匹配的编译器警告并且忽略它们,那么你没有做任何好事。请记住,C 编译器比您(或我)更了解 C!

标签: c memory memory-management memory-leaks


【解决方案1】:
void freeMatrix(int ***matrix, int k)

==>

void freeMatrix(int **matrix, int k)

编辑:

free(matrix+i) // when you do this the pointer across the whole array . 

==>

free(matrix[i])

【讨论】:

  • 我快疯了,获得鹰眼徽章 ;-)
  • @Quaker 这解决了你的问题吗?
  • 在同一个程序上,只有一个结构(3 个整数)而不是整数的相同二维数组,什么会导致此错误i.imgur.com/Ekx1aoj.png
  • 已编辑,期待您的参考
【解决方案2】:

您的“ImageMatrix”示例存在两个主要问题:

  1. 您的 createImageMatrix() 函数没有返回值。
  2. 您的freeCharsMatrix() 函数在应该使用free(matrix[i])free(*(matrix+i)) 时调用free(matrix+i)

您的附属问题与编译有关:

  1. createImageMatrix() 不使用 fpformat 参数。
  2. 函数体以heightwidth 编写,但参数为rowscols

这是您的代码的调试版本。我已将 freeCharsMatrix() 重命名为 freeImageMatrix(),因此名称更加一致。当我进行主要测试时,func_name 引用拼写为 __func__,但这是 C99 功能(GCC 4.8.1 允许,即使使用 -std=c89 -pedantic),所以我重命名了变量并提供了明确的定义,因为你最有可能使用 C89 编译器(MSVC 仅支持 23 年的标准,不支持 13 年的标准或 1 年的标准)。

您可以看到我最终是如何诊断问题的——打印出传递给free() 的地址,并将它们与malloc() 返回的地址进行比较。我花了很长时间才发现matrix[i] 等同于*(matrix+i) 而不是matrix+i

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

typedef struct Chars
{
    char A;
    char B;
    char C;
    char D;
} CHARS;

void dumpImageMatrix(CHARS **matrix, int rows, int cols);
CHARS **createImageMatrix(int height, int width);
void freeImageMatrix(CHARS **matrix, int height);

static void dump_address(const char *tag, int num, void *vp)
{
    printf("%s[%d] = %p\n", tag, num, vp);
}

static void checkalloc(void *vp)
{
    if (vp == 0)
    {
        fprintf(stderr, "Memory allocation failed\n");
        exit(1);
    }
}

CHARS **createImageMatrix(int height, int width)
{
    static const char func_name[] = "createImageMatrix";
    CHARS **res;
    int i;

    printf("-->> %s()\n", func_name);
    res = (CHARS**)malloc(sizeof(CHARS*)*height);
    checkalloc(res);
    dump_address("MTX", 0, res);

    for (i = 0; i < height; i++)
    {
        int j;
        res[i] = (CHARS*)malloc(sizeof(CHARS)*width);
        checkalloc(res[i]);
        dump_address("Row", i, res[i]);
        for (j = 0; j < width; j++)
            memset(&res[i][j], (i + j) % 26 + 'A', sizeof(CHARS));
    }
    printf("<<-- %s()\n", func_name);
    return res;
}

void freeImageMatrix(CHARS **matrix, int height)
{
    static const char func_name[] = "freeImageMatrix";
    int i;
    printf("-->> %s()\n", func_name);
    for (i = 0; i < height; i++)
    {
        dump_address("Row", i, matrix[i]);
        /*dump_address("CHK", i, matrix+i);*/
        /*dump_address("CHK", i, *(matrix+i));*/
        /*free(matrix[i]);*/
        free(*(matrix+i));
        /*free(matrix+i);*/
    }
    dump_address("MTX", 0, matrix);
    free(matrix);
    printf("<<-- %s()\n", func_name);
}

int main(void)
{
    enum { m_rows = 5, m_cols = 6 };
    CHARS **mat = createImageMatrix(m_rows, m_cols);
    dumpImageMatrix(mat, m_rows, m_cols);
    freeImageMatrix(mat, m_rows);
    return 0;
}

static void dump_Chars(CHARS c)
{
    printf("%c%c%c%c", c.A, c.B, c.C, c.D);
}

void dumpImageMatrix(CHARS **matrix, int rows, int cols)
{
    static const char func_name[] = "dumpImageMatrix";
    int i;
    printf("-->> %s()\n", func_name);
    dump_address("MTX", 0, matrix);
    for (i = 0; i < rows; i++)
    {
        int j;
        dump_address("Row", i, matrix[i]);
        for (j = 0; j < cols; j++)
        {
            if (j != 0)
                putchar(' ');
            dump_Chars(matrix[i][j]);
        }
        putchar('\n');
    }
    printf("<<-- %s()\n", func_name);
}

样本输出:

-->> createImageMatrix()
MTX[0] = 0x7f97cb4039d0
Row[0] = 0x7f97cb403a00
Row[1] = 0x7f97cb403a20
Row[2] = 0x7f97cb403a40
Row[3] = 0x7f97cb403a60
Row[4] = 0x7f97cb403a80
<<-- createImageMatrix()
-->> dumpImageMatrix()
MTX[0] = 0x7f97cb4039d0
Row[0] = 0x7f97cb403a00
AAAA BBBB CCCC DDDD EEEE FFFF
Row[1] = 0x7f97cb403a20
BBBB CCCC DDDD EEEE FFFF GGGG
Row[2] = 0x7f97cb403a40
CCCC DDDD EEEE FFFF GGGG HHHH
Row[3] = 0x7f97cb403a60
DDDD EEEE FFFF GGGG HHHH IIII
Row[4] = 0x7f97cb403a80
EEEE FFFF GGGG HHHH IIII JJJJ
<<-- dumpImageMatrix()
-->> freeImageMatrix()
Row[0] = 0x7f97cb403a00
Row[1] = 0x7f97cb403a20
Row[2] = 0x7f97cb403a40
Row[3] = 0x7f97cb403a60
Row[4] = 0x7f97cb403a80
MTX[0] = 0x7f97cb4039d0
<<-- freeImageMatrix()

【讨论】:

  • 这是我尝试使用您的printf() 调试方法时得到的结果:i.imgur.com/MEWjaKX.png 我们可以看到第一个地址使应用程序因堆错误而崩溃。由于我写问题的时间很晚,所以在编辑的代码中出现拼写错误(已修复),我想请您原谅。
猜你喜欢
  • 1970-01-01
  • 2011-10-28
  • 1970-01-01
  • 2023-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-16
  • 1970-01-01
相关资源
最近更新 更多