2014-09-25 4 views
1

Я использую код: Блок.Ошибка сегментации при доступе к массиву 2d, переданному функции

Скомпилирован следующий код (без ошибок) и при запуске получил ошибку сегментации.

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/ и столкнулся с ошибкой времени выполнения. Где я ошибаюсь? и почему отладчик показывает другой адрес ?.

+0

Я не знаком с 'станд :: VECTOR' и я не понимаю, что вы подразумеваете под «mix' cout' и 'printf'» – Sab

+0

Указатель на указатель не является двумерным массивом, простым в этом. – Lundin

+0

Тогда '* (* (a + i) + j)' должен работать правильно? – Sab

ответ

0

Если вы указали int **, в вашем случае, например, [0], результирующим типом является int *. Если вы индексируете это снова, как в [0] [0], он будет интерпретировать первый элемент (являющийся целым числом 1) (или первые два элемента на 64-разрядном) в качестве указателя на int (int *) и попытаться разыгрывать его, что явно неверно и обычно приводит к ошибке сегментации.

Ваш листинг типа C (int **) переведен в reinterpret_cast. Вот почему мне не нравятся стили C-стиля, так как не всегда очевидно, что они делают.

Вкратце: с вашим приведением в (int **) вы сообщаете компилятору, что это массив указателей на int, а это не так: это массив из int [4].

Редактировать: мои комментарии о 64-битных действительны только для платформ, где sizeof (int) всегда 4. Я верю в linux sizeof (int) == sizeof (int *).

+0

Каковы изменения (исправления) или изменения типа литья, которые я должен выполнить для запуска кода? – Sab

+0

Ваша вторая вариация, проходящая как int a [] [4], является совершенно правильной. – heinrichj

+0

Есть ли альтернативные способы прохождения? или какие изменения следует внести в 'cout << a [i] [j] <<" "' в первом коде для его запуска? – Sab

0

Заменить cout<<a[i][j]<<" "; с cout<<a[i*size+j]<<" ";

+0

Получил адрес как out put, тогда я попробовал '* a [i * size + j]' получил ошибку сегментации. – Sab

+0

Да, если вы используете 'void print (int size, int a [] [4])' version, но я говорю о 'void print (int size, int ** a)' – Andrii

0

проблемы вы столкнулись из-за типа данных обоих отличается. int arr [] [] отличается от int ** arr. Давайте посмотрим из массива 1-d, когда вы объявляете int arr [], arr это то же самое, что и int * arr. Когда вы пытаетесь получить доступ к нему, внутри [i] внутренне какой компилятор делает * (arr + i). Но когда вы объявляете int arr [] [size] data type of arr is int (* arr) [size], который отличается от int ** arr. Вот почему вы получаете ошибку. посмотреть Link

1

В первом примере

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 Интс. Когда вы передаете массив для функции, массив распадается на указатель на его первый элемент.Так что фактически функция print получает аргумент типа int *[4] - указатель на массив из 4 целых чисел, который не является чем-то print ожидает. Это ошибка. Вы скрываете эту ошибку от компилятора, говоря ему, что a имеет тип int **. Это не так. Отсюда и погрешность сегментации.

В вашем второго примере

void print(int size, int a[][4]) 

ожидает аргумент типа массива массивов из 4 Интса. Он распадается на int *[4], который является именно типом a, когда он распадается при передаче функции print. Здесь нет ошибки.

0

следующие работы для меня:

Распределение и назначение:

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); 
} 
Смежные вопросы