Как решить ошибку ошибки сегментации C ++ - PullRequest
0 голосов
/ 17 сентября 2018

Я пишу программу, которая получает массив целых чисел и его логический размер. При вызове он создает новый массив, содержащий только положительные числа из массивов.

Теперь для этого мне нужно написать функцию типа void, принимающую следующие параметры:

(int* arr, int arrSize, int** outPosArrPtr, int* outPosArrSizePTR)

Я должен использовать указатель int** outPosArrPtr для обновления базового адреса массива, содержащего положительные числа, и указатель outPosArrSizePtr для обновления логического размера массива.

теперь, когда я запускаю свой код на компиляторе xcode, логический размер обновляется до очень большого числа. Итак, когда я попытался запустить программу с помощью онлайн-компилятора GDB, я получил ошибку «Ошибка сегментации».

Из прочитанного, что означает ошибка сегментации, я узнал, что это означает, что я пытаюсь получить доступ к памяти, которая «не принадлежит мне», или памяти, которая не находится в стеке вызовов или в части кучи программы.

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

Мой код:

#include <iostream>

typedef int* IntArrPtr;
using namespace std;


int main() {
    int arrSize;
    int *ptrSize;
    ptrSize = &arrSize;

    cout << "How many integers will this array hold:\n ";
    cin >> arrSize;

    IntArrPtr a;
    a = new int[arrSize];

    fillArr(a, arrSize);

    getPosNums4(a, arrSize,&a, ptrSize);
    cout << "The new size in main is: " << arrSize << endl;

    cout <<"The new array with positive integers is:\n";
    /*for(int i =0; i<arrSize;i++) // this runs for a large size of arrSize
        cout<< a[i] << " ";
    cout<<endl; */
    return 0;
}

void fillArr(int a[], int size){
    cout << "Please enter " << size << " Integers separated by spaces\n";
    cout << "Press enter when finished >\n";
    int i;

    for (i=0;i<size;i++)
        cin >> a[i];

}

void getPosNums4(int* arr, int arrSize, int** outPosArrPtr,int* outPosArrSizePtr){
    IntArrPtr newArr;
    newArr = new int[arrSize];
    int i;
    int newIndx = 0;
    outPosArrSizePtr = &newIndx;//initiliaze the pointer.
    for(i=0;i<arrSize;i++){
        if(arr[i] > 0){
            newArr[newIndx] =arr[i];
            newIndx++;
        }
    }
    arrSize = newIndx;
    *outPosArrSizePtr = arrSize;
    cout << "The new size is of *outPosArrSizeptr is: " << *outPosArrSizePtr << endl;

    for(int j=0;j<newIndx;j++)
        outPosArrPtr[j] = &newArr[j];
    delete []newArr;
    newArr = NULL;
    for(int i=0;i<newIndx;i++)
        arr[i] = *outPosArrPtr[i];

}

пример Когда я запускаю эту программу на Xcode:

How many integers will this array hold:
 6
Please enter 6 Integers separated by spaces
Press enter when finished >
3 -1 -3 0 6 4
The new size is of *outPosArrSizeptr is: 3
The new array with positive integers is:
The new size in main is: 7445512
The program ended with exit code: 0

Ответы [ 2 ]

0 голосов
/ 17 сентября 2018

Там довольно много проблем, но самая важная из них заключается в том, что присвоение значения аргументу функции не влияет на переменную, значение которой вы передали в качестве аргумента.
Неважно, что аргумент является указателем - в указателях нет ничего особенного.

Я думаю, что происходит то, что ваш цикл «копировать туда и обратно» (я не могу понять, что он должен делать) в функции пишет вне входного массива, вызывая неопределенное поведение и, в этом случае, перезаписывая переменные в main.

Вы слишком сильно усложняете свою функцию. Стоит

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

(Думайте о параметрах как о возвращаемых значениях и обрабатывайте их последними.)

Примерно так:

void getPosNums4(int* arr, int arrSize, int** outPosArrPtr,int* outPosArrSizePtr){
    int* newArr = new int[arrSize];
    int newIndx = 0;
    for (int i = 0; i < arrSize; i++){
        if (arr[i] > 0){
            newArr[newIndx] = arr[i];
            newIndx++;
        }
    }
    *outPosArrPtr = newArr;
    *outPosArrSizePtr = newIndx;
}

Вы также не должны передавать указатели на ваши "оригиналы" для изменения этой функции, вы должны использовать новые переменные.

int main() {
    int arrSize = 0;
    cout << "How many integers will this array hold:\n ";
    cin >> arrSize;
    int* a = new int[arrSize];
    fillArr(a, arrSize);
    int * positives = nullptr;
    int positiveSize = 0;
    getPosNums4(a, arrSize, &positives, &positiveSize);
    cout << "The new size in main is: " << positiveSize << endl;

    delete [] a;
    delete [] positives;
}
0 голосов
/ 17 сентября 2018

Современный C ++ использует вектор, а не размещает массивы вручную.Ручное распределение подвержено множеству ошибок, которые очень сложно отладить.

Логика в вашем методе getPosNums4, похоже, является проблемой.Если я понимаю требование, оно должно искать положительные целые числа во входном массиве и копировать их во вновь распределенный выходной массив.Перераспределение выходного массива неоптимально, но не является реальной ошибкой.

void getPosNums4(int* arr, int arrSize, int** outPosArrPtr,int* outPosArrSizePtr){
    IntArrPtr newArr;
    newArr = new int[arrSize];
    int i;
    int newIndx = 0;
    for(i=0;i<arrSize;i++){
        if(arr[i] > 0){
            newArr[newIndx] =arr[i];
            newIndx++;
        }
    }
    *outPosArrSizePtr = newIndx;
    cout << "The new size is of *outPosArrSizeptr is: " << *outPosArrSizePtr << endl;
    *outPosArrPtr = newArr;
}

Обратите внимание, что вновь выделенный массив необходимо удалить [] вызывающей функцией, иначе произойдет утечка памяти.

Вот та же программа в современном C ++.Обратите внимание, что использование new / delete не используется, что избавляет от многих страданий.

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main() {
    vector<int> integer_vector;
    vector<int> positive_vector;

    cout << "Type in integers. Type a Q to continue:" << endl;
    int an_int;
    while(cin >> an_int)
      integer_vector.push_back(an_int);

    for_each(integer_vector.begin(),integer_vector.end(),[&](int const& n){ 
       if(n > 0)
          positive_vector.push_back(n);
    });
    cout <<"The new array with positive integers is:\n";
    for(auto const & element:positive_vector)
        cout<< element << " ";
    cout<<endl; 
    return 0;
}
...