2013-03-22 69 views
3

这是我在C++编写代码分段故障初始化INT **

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

... 现在我初始化上述使用循环如下:

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); 

但我得到分段错误执行此操作。任何人都可以帮我弄清楚我做错了什么吗?

+0

你是否在代码的任何地方为“a”分配内存? – 2013-03-22 18:59:11

+0

对不起,我错过了添加内存分配。 'a = new int * [m]; for(int i = 0; i user2175966 2013-03-22 19:03:44

+0

好的,现在问题很明显 - 增加了一个答案。 – 2013-03-22 19:08:57

回答

3
int** a; 

这只是给你一个单一的对象。 A int**对象。它根本没有指向任何地方。没有int s分配给。当您开始将int分配为存在时,您会收到未定义的行为。

此外,int**指向的内存布局的int秒的“二维数组”是像这样:在的int*秒的阵列的第一个元素的int**点,以及在所述第一元件的int*小号点在一排int s。该内存不是连续的,因为它需要间接地跳转内存,即它不是一个单独的内存块。你不能用memset来写信给它。

如果你只是想的int个固定的编译时大小的二维数组,这样做:

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]; 
} 

但这很丑陋!

+0

'int a [N] [M];' - 仍然是C99的一部分,也可以作为GCC的扩展,变长数组不是C++标准的一部分。 – LihO 2013-03-22 19:05:00

+0

@LihO其中'N'和'M'是常量表达式。 – 2013-03-22 19:05:31

+0

你现在我使用刚刚描述的丑陋的部分。所以会改进它 – user2175966 2013-03-22 19:10:16

1

使用int **您通常不会有单个连续的内存块。假设你正确使用它,你会得到一个指针数组。这些指针中的每一个都会为它分别分配一个数组。

既然如此,则无法将您的循环转换为单个memset(并且仍然会获得定义的行为)。

0

我觉得问题是内存没有分配给实际存储。变量a只是指针(除此之外未初始化)。它指向哪个地方?

3
int** a; 

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

“现在我初始化上述使用循环”

你是不是在你的for环路初始化它,你只是想分配0的元素,唐” t存在,这产生了未定义的行为。您需要可以动态分配内存,这些元素或者还甚至更好:使用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对象被破坏将被自动清理)
+0

我试图优化它使用for循环的主要原因是花费很长时间,我必须减少它 – user2175966 2013-03-22 19:15:14

+0

你确定'for'循环需要很多时间?你是否用最近的编译器(例如GCC 4.7或4.8中的'g ++')和启用优化(例如'-O2'或'-O3')编译? – 2013-03-22 19:20:22

+0

我现在看到了区别。我编译使用g ++和优化启用和更快。但是我试图优化的实际代码确实使用了这些选项。谢谢 – user2175966 2013-03-22 19:29:23

0

你说你分配这样的:

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

像杰里Conffin说 - 这不会给你一个连续的记忆块。 每个新数组(new int[n])将被分配到一个可能完全不同的位置,并且memset只能在连续的块上工作,因此您必须“手动”重置每个数组。012w顺便说一句 - 我敢肯定,你不会去查看在循环中使用memset的任何性能改进(memset本身使用实现使用循环,我认为)。