带有二维数组的分段错误 shmat()
Segmentation fault shmat() with 2d array
正在尝试在共享内存中分配二维数组。分配期间执行 returns 分段错误(我认为)。我应该用另一种方式做作业吗?这是我的代码:
...
#define KEYSM 46378
#define X 10
#define Y 10
int main(){
int i, j;
int shm_id;
int **addressArray;
if((shm_id = shmget(KEYSM, sizeof(int[X][Y]), IPC_CREAT | 0666)) == -1){
perror("shmget");
exit(-1);
}
if((addressArray = (int **)shmat(shm_id, NULL, 0)) == (int **)-1){
perror("shmat");
exit(-1);
}
for(i = 0; i < X; i++){
for(j = 0; j < Y; j++){
if(i % 2 != 0)
addressArray[i][j] = -1;
else
addressArray[i][j] = 0;
}
}
...
}
段错误是运行时错误,但您的代码甚至不应该编译,请查看以下语句(缺少括号):
if ( ( addressArray = ( int** ) shmat ( shm_id, NULL, 0 ) == ( int** ) -1 )
如果任务失败怎么办? perror 是否终止进程?没有。但是您仍然可以访问下面的数组。很可能是段错误的来源。
正如 mch 指出的那样:
// i is not declared
for(i = 0; i < X; i++){
// j is not declared, after j < Y, use semicolon instead of comma
for(j = 0; j < Y, j++){
// if the result is not zero you're doing an assignment
if(i % 2 != 0)
addressArray[i][j] = -1;
// but immediately after you assign a zero,
// previous statement -> useless
// 'else' is missing here
addressArray[i][j] = 0;
}
}
你的问题在于 - (你的?) - 对真正的二维数组和指针→指针→值间接的区别的误解。
当您定义一个 int **a
时,它被解释为指向另一个指针的指针,然后该指针引用一个 int
。将从 malloc
或 shmat
等分配函数获得的指针分配给这样的双指针,然后就 C 的语义而言,它期望此内存分配包含更多指针。因此,如果您执行双重取消引用,并且那里没有有效的指针,它就会掉下来。
这种误解因以下事实而进一步加深,即在 C 中您可以有效地编写 int a[X][Y];
并使用 a[i][j]
取消引用它。理解这一点的关键见解是,第一个“一半”,即具有这样定义的数组的 a[i]…
衰减为 int*
指针,指向 [=19 中的第 0 个元素=]“列”。另一半 …[j]
然后取消引用这个隐式“出现”的指针。
C 中的多维数组具有欺骗性,我强烈反对这样使用它们。此外,您将很难正确地使用它们实现特定的填充和行对齐,而不跳过一些非常烦人的算法。
到目前为止,只需明确地写下计算结果就更容易了,而且还可以精确控制填充和对齐。
假设我们要创建一个 int
的二维数组,该数组应与 long long
的大小对齐
size_t const array_height = ...;
size_t const array_width = ...;
size_t const alignment = sizeof(long long);
size_t const row_size = array_width * sizeof(int);
size_t const row_stride =
alignment * ((row_size + alignment-1) / alignment);
size_t const array_size = array_height * row_stride;
int const shm_id = shmget(KEYSM, array_size, IPC_CREAT | 0666);
if( 0 > shm_id ){
perror("shmget");
exit(-1);
}
int *const array = shmat(shm_id, NULL, 0);
if( (void*)-1 == array ){
perror("shmat");
exit(-1);
}
for(size_t j = 0; j < array_height; ++j){
int *const row = array + j * row_stride;
for(size_t i = 0; i < array_width; ++i){
row[i] = (i % 2) ? -1 : 0;
}
}
正在尝试在共享内存中分配二维数组。分配期间执行 returns 分段错误(我认为)。我应该用另一种方式做作业吗?这是我的代码:
...
#define KEYSM 46378
#define X 10
#define Y 10
int main(){
int i, j;
int shm_id;
int **addressArray;
if((shm_id = shmget(KEYSM, sizeof(int[X][Y]), IPC_CREAT | 0666)) == -1){
perror("shmget");
exit(-1);
}
if((addressArray = (int **)shmat(shm_id, NULL, 0)) == (int **)-1){
perror("shmat");
exit(-1);
}
for(i = 0; i < X; i++){
for(j = 0; j < Y; j++){
if(i % 2 != 0)
addressArray[i][j] = -1;
else
addressArray[i][j] = 0;
}
}
...
}
段错误是运行时错误,但您的代码甚至不应该编译,请查看以下语句(缺少括号):
if ( ( addressArray = ( int** ) shmat ( shm_id, NULL, 0 ) == ( int** ) -1 )
如果任务失败怎么办? perror 是否终止进程?没有。但是您仍然可以访问下面的数组。很可能是段错误的来源。
正如 mch 指出的那样:
// i is not declared
for(i = 0; i < X; i++){
// j is not declared, after j < Y, use semicolon instead of comma
for(j = 0; j < Y, j++){
// if the result is not zero you're doing an assignment
if(i % 2 != 0)
addressArray[i][j] = -1;
// but immediately after you assign a zero,
// previous statement -> useless
// 'else' is missing here
addressArray[i][j] = 0;
}
}
你的问题在于 - (你的?) - 对真正的二维数组和指针→指针→值间接的区别的误解。
当您定义一个 int **a
时,它被解释为指向另一个指针的指针,然后该指针引用一个 int
。将从 malloc
或 shmat
等分配函数获得的指针分配给这样的双指针,然后就 C 的语义而言,它期望此内存分配包含更多指针。因此,如果您执行双重取消引用,并且那里没有有效的指针,它就会掉下来。
这种误解因以下事实而进一步加深,即在 C 中您可以有效地编写 int a[X][Y];
并使用 a[i][j]
取消引用它。理解这一点的关键见解是,第一个“一半”,即具有这样定义的数组的 a[i]…
衰减为 int*
指针,指向 [=19 中的第 0 个元素=]“列”。另一半 …[j]
然后取消引用这个隐式“出现”的指针。
C 中的多维数组具有欺骗性,我强烈反对这样使用它们。此外,您将很难正确地使用它们实现特定的填充和行对齐,而不跳过一些非常烦人的算法。
到目前为止,只需明确地写下计算结果就更容易了,而且还可以精确控制填充和对齐。
假设我们要创建一个 int
的二维数组,该数组应与 long long
size_t const array_height = ...;
size_t const array_width = ...;
size_t const alignment = sizeof(long long);
size_t const row_size = array_width * sizeof(int);
size_t const row_stride =
alignment * ((row_size + alignment-1) / alignment);
size_t const array_size = array_height * row_stride;
int const shm_id = shmget(KEYSM, array_size, IPC_CREAT | 0666);
if( 0 > shm_id ){
perror("shmget");
exit(-1);
}
int *const array = shmat(shm_id, NULL, 0);
if( (void*)-1 == array ){
perror("shmat");
exit(-1);
}
for(size_t j = 0; j < array_height; ++j){
int *const row = array + j * row_stride;
for(size_t i = 0; i < array_width; ++i){
row[i] = (i % 2) ? -1 : 0;
}
}