简体   繁体   English

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

[英]Segmentation fault on using memset instead of for loops to initialize int**

Here is my code in c++ 这是我在c ++中的代码

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

... Right now i am initializing the above using for loops as follows: ...现在我正在使用for循环初始化上面的内容,如下所示:

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

I am trying to improve performance and hence thought using memset would be a good idea . 我正在努力提高性能,因此使用memset的想法是个好主意。 So modified my code to use memset instead of for loop as follows: 所以修改我的代码使用memset而不是for循环,如下所示:

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

But i get Segmentation fault on executing this . 但是我在执行此操作时遇到Segmentation错误。 Can anybody help me figure out what I am doing wrong? 任何人都可以帮我弄清楚我做错了什么?

int** a;

This just gives you a single object. 这只是给你一个对象。 A int** object. 一个int**对象。 It doesn't point anywhere at all. 它根本不指向任何地方。 There are no int s to assign to. 没有要分配的int When you start assigning to the int s as though they exist, you get undefined behaviour. 当您开始分配int ,就好像它们存在一样,您会得到未定义的行为。

In addition, the memory layout of an int** pointing to a "2d array" of int s is like so: the int** points at the first element in an array of int* s, and the int* s point at the first elements in an array of int s. 此外,一个的存储器布局int**指向的“二维数组” int s是像这样:在int**在阵列的第一个元素点int* s,并且int* s的点int数组中的第一个元素。 This memory is not contiguous because it requires indirection to jump around memory, ie it's not a single block of memory. 这个内存不是连续的,因为它需要间接跳转内存,即它不是单个内存块。 You can't just write to it using memset . 你不能只使用memset写它。

If you just want a fixed compile-time sized 2D array of int s, do: 如果您只想要一个固定的编译时大小的int数组,请执行以下操作:

int a[N][M];

where N and M are constant expressions. 其中NM是常量表达式。 This is stored contiguously, but I still don't recommend using memset . 连续存储的,但我仍然不建议使用memset

Or use a standard container, such as: 或使用标准容器,例如:

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

If you need it of dynamic size, try: 如果您需要动态大小,请尝试:

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

Alternatively, you can stick with your int** and make sure you dynamically allocate the int* s and int s: 或者,您可以坚持使用int**并确保动态分配int* s和int s:

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

But this is ugly! 但这太丑了!

int** a;

is just a declaration of a pointer to pointer to int . 只是指向int的指针的声明。

"Right now i am initializing the above using for loops" “现在我正在使用for循环初始化上面的内容”

You are not initializing it in your for loops, you're just trying to assign 0 to the elements that don't exist, which produces an undefined behavior . 您没有在for循环中初始化它,您只是尝试将0分配给不存在的元素,这会产生未定义的行为 You need to either dynamically allocate the memory for these elements or yet even better: use std::vector instead: 您需要为这些元素动态分配内存,或者甚至更好:使用std::vector代替:

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

"I am trying to improve performance" “我正在努力改善表现”

Don't do that unless it is necessary. 除非有必要,否则不要这样做。 Don't optimize prematurely. 不要过早优化。


EDIT : After you mentioned that you are facing the performance issues already, here's what you could do: Instead of this two-dimensional C-style array: 编辑 :在你提到你已经面临性能问题之后,这就是你可以做的:而不是这个二维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

you could use one-dimensional std::vector : 你可以使用一维std::vector

std::vector<int> vec(rows * cols, 0);
...
vec[i * cols + j] = 7;   // equivalent of vec[i][j]
this will have more advantages: 这将有更多的优势:
  • your 2D array will be stored within the continuous block of memory 您的2D数组将存储在连续的内存块中
  • this block of memory will be allocated at once, not in many small pieces 这块内存将立即分配,而不是分成许多小块
  • frequent accessing of elements will be faster thanks to spatial locality 由于空间局部性,频繁访问元素将更快
    (elements that are "near" will be available in cache memory thus your (“靠近”的元素将在缓存中提供,因此您的
    program will not have to load them from the main memory) 程序不必从主内存加载它们)
  • and you will not be responsible for the memory management 并且您不负责内存管理
    (memory will be cleaned up automatically once the vector object is destructed) (一旦vector对象被破坏,内存将自动清理)

With an int ** you won't normally have a single, contiguous block of memory. 使用int ** ,通常不会有一个连续的内存块。 Assuming you use it correctly, you'll have an array of pointers. 假设你正确使用它,你将有一个指针数组。 Each of those pointers will then have an array allocated for it individually. 然后,每个指针都将分别为其分配一个数组。

That being the case, you can't convert your loops to a single memset (and still get defined behavior). 在这种情况下,您无法将循环转换为单个memset (并且仍然可以获得定义的行为)。

I think problem is with the memory not allocated for actual storage. 我认为问题在于没有为实际存储分配内存。 Variable a is only pointer (in addition not initialized). 变量a只是指针(另外没有初始化)。 To what place it points? 它指向的地方?

You said you allocated it like this: 你说你像这样分配了它:

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

Like Jerry Conffin said - This won't give you a single, contiguous block of memory. 就像Je​​rry Conffin所说 - 这不会给你一个连续的内存块。 Each new array ( new int[n] ) will be allocated in a possibly totally different location and memset only works on contiguous blocks, so you have to reset each of them "by hand" Btw - I'm pretty sure you're not going to see any performance improvements from using memset over a loop (memset itself use implemented using a loop I think). 每个新数组( new int[n] )将分配在一个可能完全不同的位置,memset仅适用于连续的块,所以你必须“手动”重置每个数组顺便说一下 - 我很确定你不是将看到在循环中使用memset的任何性能改进(我认为memset本身使用循环实现)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM