在 class 中访问 malloc 二维数组时出现段错误

Seg Fault upon accessing malloc'd 2d array in class

这是一个 class,其中包含一个名为 "map" 的二维字符数组。首先,我将 [mapDimension] char*s 分配给一个 char**。然后,我将 [mapDimension] 字符分配给每个 char*。我这样做而不是静态的:char map[mapDimension][mapDimension] 因为虽然这适用于小数字,但一旦 mapDimension 超过 2500 左右,它也会出现段错误。我想在堆上而不是堆栈上分配内存,这样我就可以容纳更多。

构造函数中的最后两行是将二维数组中的每个字符初始化为 0,然后将中心的一个设置为 5。

#define mapDimension 1000    

class Field 
{
private:
    int i;
public:
    char** map = (char**)malloc(mapDimension * sizeof(char*));
    Field()
    {
        for(i = 0; i < mapDimension; i++)
            map[i] = (char*)malloc(mapDimension * sizeof(char));
        memset(map, 0, mapDimension*mapDimension*sizeof(char));
        map[mapDimension/2][mapDimension/2] = 5;
    }
};

int main()
{
    Field field;
    return 0;
}

这种动态方法也会出现段错误。我做错了什么?

    memset(map, 0, mapDimension*mapDimension*sizeof(char));

您正在清除 map 数组( 指针数组 ),因此 map[x] 现在包含 NULL。您可能应该在循环中使用 map[i] 来清除分配的内存。

但是

  1. 当你分配内存时,你应该释放它(有 malloc,没有空闲可见)
  2. 在 C++ 中使用 new[]delete[] 而不是 malloc
  3. 更好 - 使用 std::vector<std::vector<char>>

此声明无效

memset(map, 0, mapDimension*mapDimension*sizeof(char));

您分配了多个内存范围,而不是一个连续的存储区域。

你必须使用循环。例如

    for ( i = 0; i < mapDimension; i++ ) memset( map[i], 0, mapDimension );

并且您的 class 必须有一个析构函数来释放分配的内存。

例如

~Field()
{
    for( i = 0; i < mapDimension; i++ ) free( map[i] );
    free( map );
}

最好让mapDimension像一个size_t类型的静态常量变量,而不是使用宏定义。

请注意,在 C++ 中您应该使用运算符 new 而不是 C 函数 malloc

您也可以简单地使用容器 std::vector<std::string> 而不是手动分配的数组。

  • 首先,可以分配您的数组,这样您就可以一次性 memset 整个数组。但是为此你必须将二级内存分配为一个连续的内存块,然后在行之间分配它

    Field()
    {
      char *data_memory = (char *) malloc(mapDimension * mapDimension * sizeof(char));
    
      for (i = 0; i < mapDimension; i++)
        map[i] = data_memory + i * mapDimension;
      ...
    }
    
  • 其次,如果您将分配方法更改为 "single block allocation"(如上所述),那么为了 memset 整个事情,您必须按如下方式进行

    memset(map[0], 0, mapDimension * mapDimension * sizeof(char));
    

    memset(&map[0][0], 0, mapDimension * mapDimension * sizeof(char));
    

    注意memset的第一个参数。

    但是如果您坚持当前的分配方法,那么您就可以忘记在整个数组上使用 memset。您的数组在内存中不连续。你不能 memset 整件事。您所能做的就是 memset 每行单独

    for (i = 0; i < mapDimension; i++)
      memset(map[i], 0, mapDimension * sizeof(char));
    
  • 第三,将 i 声明为 class 的成员而不是使用局部变量 i 是个坏主意。此外,对第一个 malloc 使用 in-class 初始化程序也是一个坏主意。此外,在 C++ 中,您应该更喜欢使用 new/new[] 而不是 malloc,甚至更不用说您应该更喜欢使用 std::vector 而不是手动数组内存管理。