如何解决分段错误错误C++

How to solve segmentation fault error C++

本文关键字:错误 分段 C++ 解决 何解决      更新时间:2023-10-16

我正在编写一个程序,该程序获取整数数组及其逻辑大小。调用时,它会创建一个新数组,仅包含数组中的正数。

现在,为了做到这一点,我需要编写一个 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 spacesn";
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

那里有很多问题,但最关键的问题是,为函数的参数赋值对作为参数传递的值的变量没有影响。
参数是指针并不重要——指针没有什么特别之处。

我认为正在发生的事情是您在函数中的"来回复制"循环(我不明白它应该做什么(正在输入数组之外写入,导致未定义的行为,在这种情况下,覆盖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;
}

现代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;
}