Ошибка сегментирования что делать?

203
28 февраля 2018, 09:18

Вылетает ошибка сегментирования (сделан дамп памяти).
Если не сложно, объясните, что именно не так. И почему возникают такие ошибки.

P.S: Знаю, ошибка новичковая но в инете так и не нашел ничего дельного. Так что прошу помощи тут.

Код программы:

    #include <iostream>
    #include <vector>
    using namespace std;
    int  swape(int **matrix, int i, int imax, int n){
      int *buf = new int[n];
      for(int j=0;j<n;j++){
        buf[j] = matrix[i][j];
      }
      for(int j=0;j<n;j++){
        matrix[i][j]=matrix[imax][j];
      }
      for(int j=0;j<n;j++){
        matrix[imax][j]=buf[j];
      }
      return **matrix;
    }
    int main(){
      int **matrix;
      cout<<"Введите размерность"<<endl;
      int n;
      cin>>n;
      matrix = new int*[n];
      for(int i=0;i<n;i++)  matrix[i] = new int[n];
      cout<<"Заполните масив"<<endl;
      for(int i=0; i<n;i++){
        for(int j=0;j<n;j++){
          cout<<"Елемент х["<<i<<"]["<<j<<"]=";
          cin>>matrix[i][j];
        }
      }
      for(int i=0; i<n;i++){
        for(int j=0;j<n;j++){
          cout<<matrix[i][j]<<"  ";
        }
        cout<<""<<endl;
      }
      swape(matrix,n,n-1,n);
      cout<<"\n";
      for(int i=0; i<n;i++){
        for(int j=0;j<n;j++){
          cout<<matrix[i][j]<<"  ";
        }
        cout<<""<<endl;
      }
      cout<<"hello world"<<endl;
      return 0;
    }
Answer 1

У Вас в функцию swape() передается вторым параметром размерность массива n, которое внутри используется как индекс. Поскольку n всегда больше, чем максимально допустимое значение индекса, то Вы и получаете сегфолт. Если вместо

swape(matrix,n,n-1,n);

написать

swape(matrix,n-1,n-1,n);

все будет чинно и гладко. Однако, похоже, что swape() ничего полезного не делает, в смысле, матрица остается такой же.

$ ./foo
Введите размерность
3
Заполните масив
Елемент х[0][0]=1
Елемент х[0][1]=2
Елемент х[0][2]=3
Елемент х[1][0]=4
Елемент х[1][1]=5
Елемент х[1][2]=6
Елемент х[2][0]=7
Елемент х[2][1]=8
Елемент х[2][2]=9
1  2  3  
4  5  6  
7  8  9  
1  2  3  
4  5  6  
7  8  9  
hello world
$
Answer 2
  1. Кроме указанной ошибки о неверном индексе при вызове функции swape() Вы пытаетесь вернуть двойной указатель int ** вместо заявленного в определении функции значения int. Уверен, компилятор вопил об этом так, что должны были услышать даже в Мексике.

  2. Вы в swape() выделяете память под bufи не удаляете ее. Получаете утечку памяти.

  3. Вам совершенно не нужно копировать строки, да еще и создавая промежуточный динамический массив. У Вас массив указателей, а значит, для обмена строк достаточно обменять значения всего двух ячеек "внешнего" массива. Что-то в таком роде (упрощенно):

    void swap_rows(int **matrix, int i, int imax, int n)
    {
        int *tmp     = matrix[i];
        matrix[i]    = matrix[imax];
        matrix[imax] = tmp;
    }

    Размер матрицы n здесь можно использовать для проверок на тему, не вышли ли за пределы входные параметры i и imax.

Хотя, наверное, лучше сразу передавать в функцию адреса этих ячеек массива, чтобы было всего 2 аргумента:

    void swap_rows2(int **row1, int **row2)
    {
        int *tmp = *row1;
        *row1 = *row2;
        *row2 = tmp;
    }

и вызывать, соответственно как swap_rows2(&matrix[n-2], &matrix[n-1]);.

При этом, лучше в функции добавить еще и всякие проверки, например, чтобы не пытались менять местами одну и ту же строку ;-) (ну, в этом случае можно просто молча выйти из функции... или еще и вывести какое-то сообщение - поскольку такая ситуация явно ошибочна).

Answer 3

Имя Двумерного массива можно и лучше передавать как указатель, а не указатель на указатель - это внесет ясность и эффективность кода, а также код будет короче. Например так ( я пишу пример только потому что вы уже написали другую версию )

#include <iostream>
using namespace std;
void  m_swape(int *matrix, const unsigned row_size,  unsigned row1, unsigned row2){
    row1 %= row_size; // просто заставляю не выходить за пределы массива
    row2 %= row_size;
    int t = 0;     // временная переменная для хранения и дальнейшего использования
    for(unsigned j=0; j < row_size; ++j){
        t = matrix[row1 * row_size + j];
        matrix[row1 * row_size + j] = matrix[row2 * row_size + j];
        matrix[row2 * row_size + j] = t;
    }
}
int main()
{    
       cout<<"include size: "<<endl;
       int n;
       cin>>n;
       int* matrix = new int[n * n];
       cout<<"fill array: "<<endl;
       for(int i=0; i<n; ++i){
         for(int j=0;j<n; ++j){
           cout<<"Element x["<<i<<"]["<<j<<"]=";
           cin>>matrix[i*n + j];
         }
       }
       for(int i=0; i<n; ++i){
         for(int j=0;j<n; ++j){
           cout<<matrix[i * n + j]<<"  ";
         }
         cout<<""<<endl;
       }
       m_swape(matrix, n, n - 2, n - 1);
       cout<<"\n";
       for(int i=0; i<n;i++){  // специально оставил как есть
         for(int j=0;j<n;j++){
           cout<<matrix[i * n + j]<<"  ";
         }
         cout<<""<<endl;
       }
       cout<<"hello world"<<endl;
    return 0;
}

тоесть вы передаете в функцию любые две строки, которые хотите поменять местами. И еще одно маленькое замечание, которое не влияет на результат: Старайтесь в циклах не использовать постинкремент, поскольку он каждый раз создает временное переменное - не нужно писать i++ там, где можно писать ++i

READ ALSO
Изменить COM-порт устройства программно

Изменить COM-порт устройства программно

У меня подключено устройство (arduino), оно определяется и подключается к какому-нибудь COM-портуНомер порта можно изменить через Устройства и принтеры...

186
Время выполнения программы

Время выполнения программы

Узнаю время работы так:

192
Обнуление строки string

Обнуление строки string

Для того, что бы сделать строку временно пустой, я использую

197