使用 memset 而不是 for 循环初始化 int** 时出现分段错误



这是我在 c++ 中的代码

int** a;
try{
  a = new int*[m];
  for(int i = 0; i<m;i++)
    a[i] = new int[n];
}

。现在我正在使用 for 循环初始化上述内容,如下所示:

for(int i = 0; i<m; i++)
  for(int j = 0; i<n; j++)
      a[i][j] = 0;

我正在尝试提高性能,因此认为使用 memset 将是一个好主意。所以修改了我的代码以使用 memset 而不是 for 循环,如下所示:

memset(a, 0, sizeof(a[0][0]) * m * n);

但是我在执行这个时得到分段错误.谁能帮我弄清楚我做错了什么?

int** a;

这只给你一个对象。int**对象。它根本不指向任何地方。没有要分配到的int。当你开始分配给int时,就好像它们存在一样,你会得到未定义的行为。

此外,指向 int s 的"2d 数组"的int**的内存布局如下所示:int**指向 int* s 数组中的第一个元素,int* s 指向 int s 数组中的第一个元素。此内存不是连续的,因为它需要间接寻址才能在内存中跳转,即它不是单个内存块。你不能只用memset写入它。

如果您只需要一个固定的编译时大小的 int 2D 数组,请执行以下操作:

int a[N][M];

其中NM是常量表达式。这是连续存储的,但我仍然不建议使用 memset .

或使用标准容器,例如:

std::array<std::array<int, M>, N> a;

如果您需要动态大小,请尝试:

std::vector<std::vector<int>> a(M, std::vector<int>(N));

或者,您可以坚持使用int**并确保动态分配int* s 和 int s:

int** a = new int*[M];
for (i = 0; i < N; i++) {
  a[i] = new int[N];
}

但这很丑陋!

int** a;

只是指向int的指针的声明。

"现在我正在使用 for 循环初始化上述内容">

您不是在for循环中初始化它,只是尝试将0分配给不存在的元素,这会产生未定义的行为。您需要为这些元素动态分配内存,或者更好的是:改用std::vector

std::vector< std::vector<int> > a(m, std::vector<int>(n, 0));

"我正在努力提高性能">

除非有必要,否则不要这样做。不要过早优化。


编辑:在您提到您已经面临性能问题之后,您可以执行以下操作:而不是这个二维 C 样式数组:

int** a = new int*[m];      // m = number of rows
for(int i = 0; i < m; i++)
    a[i] = new int[n];      // n = number of columns

您可以使用一维std::vector

std::vector<int> vec(rows * cols, 0);
...
vec[i * cols + j] = 7;   // equivalent of vec[i][j]
这将具有更多优势:
  • 您的 2D 阵列将存储在连续的内存块中
  • 这个内存块将一次分配,而不是很多小块
  • 由于空间局部性
    ,元素的频繁访问将更快("接近"的元素将在缓存中可用,因此您的
    程序不必从主内存加载它们(
  • 并且您将不负责内存管理
    (一旦vector对象被破坏,内存将自动清理(

使用int **,您通常不会有一个连续的内存块。假设您正确使用它,您将拥有一组指针。然后,这些指针中的每一个都将单独为其分配一个数组。

在这种情况下,您无法将循环转换为单个memset(并且仍然可以获得定义的行为(。

我认为问题在于未为实际存储分配的内存。变量 a 只是指针(此外未初始化(。它指向什么地方?

你说你是这样分配的:

a = new int*[m]; 
for(int i =0; i<m ;i++) a[i] = new int[n];

就像Jerry Conffin说的 - 这不会给你一个单一的,连续的内存块。每个新数组(new int[n](将被分配到一个可能完全不同的位置,memset只适用于连续的块,所以你必须"手动"重置它们中的每一个。顺便说一句 - 我很确定你不会看到通过循环使用 memset 的任何性能改进(我认为 memset 本身使用循环实现(。

相关内容

  • 没有找到相关文章