访问传递给函数的二维数组时出现分段错误
Segmentation fault from accessing 2d array passed to a function
我正在使用代码:块。
编译了以下代码(没有错误),运行时出现分段错误。
void print(int size, int **a)
{
for(int i=0;i<size;i++)
{
for(int j=0;j<size;j++)
{
cout<<a[i][j]<<" ";/**Segmentation fault here**/
}
cout<<endl;
}
}
int main()
{
int a[4][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
int size = sizeof(a)/sizeof(a[0]);
print(size,(int **)a);
return 0;
}
我尝试使用不同的方法传递数组:
void print(int size, int a[][4])
{
for(int i=0;i<size;i++)
{
for(int j=0;j<size;j++)
{
cout<<a[i][j]<<" ";
}
cout<<endl;
}
}
int main()
{
int a[4][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
int size = sizeof(a)/sizeof(a[0]);
print(size,a);
return 0;
}
我没有得到任何错误,代码运行成功。
对于第一个代码,我没有使用a[i][j]
,而是尝试使用*(*(a+i)+j)
,但出现了分割错误。
然后,我在分段故障点调试了第一个代码,并吸收了以下内容:
> p a
$1 = (int **) 0x22fd30
> p *a
$2 = (int *) 0x200000001
> p **a
Cannot access memory at address 0x200000001
我相信a
保存了2d数组的第一个地址。但是对于p**a,在错误消息中显示了不同的地址。
然后我在中运行了第一个代码http://ideone.com/并遇到运行时错误。我哪里搞错了?为什么调试器显示不同的地址?。
在您的第一个示例中
void print(int size, int **a)
需要类型为的第二个参数,指针指向int。但是这里
int a[4][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
print(size,(int **)a);
您传递一个类型为的变量,数组由4个4 int的数组组成。当您将数组传递给函数时,数组会衰减为指向其第一个元素的指针。所以实际上函数print
得到类型为int *[4]
的参数-指向4个int数组的指针,这不是print
所期望的。这是个错误。对于编译器告诉他a
的类型为int **
,您可以隐藏此错误。事实并非如此。因此出现了分段错误。
在你的第二个例子
void print(int size, int a[][4])
需要一个类型为的参数,该数组包含4个整数的数组。当它在传递给print
函数时衰减时,它衰减为int *[4]
,这正是a
的类型。此处没有错误。
如果对一个int**进行索引,例如在您的情况下为[0],则结果类型为int*。如果你再次对其进行索引,就像在[0][0]中一样,它会将第一个元素(整数1)(或64位上的前两个元素)解释为指向int(int*)的指针,并试图取消对它的引用,这显然是不正确的,通常会导致分段错误。
您的C样式强制转换(int**)将被转换为interpret_cast。这就是为什么我不喜欢C风格的类型转换,因为它们的作用并不总是显而易见的
简言之:通过对(int**)的强制转换,你告诉编译器这是一个指向int的指针数组,但事实并非如此:它是一个int[4]的数组。
编辑:我对64位的评论只适用于sizeof(int)总是4的平台。我相信在linux上sizeof(int)==sizeof(int*)。
用cout<<a[i*size+j]<<" ";
替换cout<<a[i][j]<<" ";
您面临的问题是因为两者的数据类型不同。int arr[]不同于int**arr。让我们从一维数组中看到,当您声明int arr[]时,arr与int*arr相同。当您试图在内部访问它时,arr[i]编译器会做什么*(arr+i)。但是当您声明int arr[][size]时,arr的数据类型是int(*arr)[size],这与int**arr不同。这就是你出错的原因。请参阅此链接
以下对我有效:
分配和分配:
int** foo( int N, int M)
{
int** arr;
arr = (int **)malloc(sizeof(int *)*N);
for(int i=0; i < N; i++) {
arr[i] = (int *)malloc(sizeof(int)*M);
}
int x=0;
for(int i=0;i<N;i++)
{
for(int j=0;j<M;j++)
{
arr[i][j]=x;
x++;
}
}
return arr;
}
现在你可以这样使用它:
void print(int size, int a[][4])
{
for(int i=0;i<size;i++)
{
for(int j=0;j<size;j++)
{
cout<<a[i][j]<<" ";
}
cout<<endl;
}
}
int main()
{
int N=2;
int M=3;
int** foo = bar(N,M);
print(arr,N,M);
}
- 在某些循环内使用vector.push_back时出现分段错误
- 为什么在运行时没有向我们提供有关分段错误的更多信息?
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- 当我的阵列太大时出现分段错误
- 分段错误当我试图运行程序时出错
- 在c++中初始化矩阵时出现分段错误(核心转储)
- 尝试使用集合函数时出现分段错误
- 我无法缩小此分段错误的原因
- g++的分段错误(在NaN上使用to_string两次时)
- 我是如何在这段代码中出现分段错误的
- 创建结构的数组时遇到分段错误
- 在c++中键入向量中的所有值后,得到分段错误(核心转储)
- 在 c++ 中实现 Trie 时出现分段错误
- 为什么 fstream 在打开带有格式的文件时会导致分段错误?
- 为什么我遇到分段错误?
- 动态类的分段错误(家庭作业问题)
- 分段错误 - 读取初始化指针的数组
- 如何摆脱C ++中的分段错误错误?
- 使用 CTYPE 时出现分段错误
- 为什么代码给出分段错误?