Hi, i have a problem with segmentation fault in c++ - c++

I'm working on a small sorting program with vector of pairs. But I'm getting a segmentation fault. I want to make a program that gets as input an vector of pairs containing files with there names and sizes, sorts the vector by the sizes of the files...
#include <iostream>
#include <vector>
#include <string>
using namespace std;
pair<string, int> min (vector<pair<string, int>> list){
pair<string, int> min;
for(int i = 0;i < list.size(); i++){
for(int j = 1; j < list.size(); i++){
if(list[i].second <= list[j].second)
min = list[i];
}
}
return min;
}
vector<pair<string, int>> sort (vector<pair<string, int>>& list){
vector<pair<string, int>> sorted;
for(int i = 0; i <= list.size(); i++){
sorted.push_back(min(list));
list.erase(list.begin()+(i-1));
}
return sorted;
}
int main(){
vector<pair<string, int>> files = {
{"f1", 30},
{"f2", 50},
{"f3", 25},
{"f4", 42},
{"f5", 10}
};
//min(files);
sort(files);
}

Problem 1
The problem is that after list.erase(list.begin()+(i-1)); the size of the vector has changed and so you need to recalculate the size and the indices used.
Problem 2
Additionally, for the inner loop involving j you're incrementing the outer loop variable i:
//------------------------------vvvv---->this should be j
for(int j = 1; j < list.size(); i++)
Problem 3
//-----------------------v------>what if i = 0? Undefined behavior
list.erase(list.begin()+(i-1));
In the above shown statement when i = 0 the expression list.erase(list.begin()+(0-1)) will lead to undefined behavior which is most probably the cause of seg fault you're observing.
Undefined behavior means anything1 can happen including but not limited to the program giving your expected output. But never rely(or make conclusions based) on the output of a program that has undefined behavior. The program may just crash.
So the output that you're seeing(maybe seeing) is a result of undefined behavior. And as i said don't rely on the output of a program that has UB. The program may just crash.
For example here the program doesn't crash but here it crashes.
So the first step to make the program correct would be to remove UB. Then and only then you can start reasoning about the output of the program.
Note
There may be additional logical problems in your code.
1For a more technically accurate definition of undefined behavior see this where it is mentioned that: there are no restrictions on the behavior of the program.

Related

Getting Segmentation Fault error in C++ code

#include<bits/stdc++.h>
using namespace std;
//FIRST REPEATING ELEMENT (APPROACH 2)
int main()
{
cout<<"running";
int n;
cin>>n;
int arr[n];
for(int i=1; i<=n; i++)
cin>>arr[i];
const int N = 1e5+2;
int idx[N];
for(int i=0;i<N;i++)
idx[i] = -1;
int minidx = INT_MAX;
for(int i=0;i<n;i++)
{
if(idx[arr[i]] != -1)
minidx = min(minidx, idx[arr[i]]);
else
idx[arr[i]] = i;
}
if(minidx == INT_MAX)
cout<<"-1"<<endl;
else
cout<<minidx + 1<<endl;
return 0;
}
I am writing this code for "First Repeating Element" question and trying to get the index of the first element that repeats.
On debugging, I am getting segmentation fault.
int main()
{ (in this line)
What does it mean and what can I do to remove this.
const int N = 1e5+2;
int idx[N];
That sounds like a big array to be allocated on the stack (400kb!). Try using malloc() to allocate an array of that size. Change that to something like
const int N = 1e5+2;
int* idx = (int*)malloc(N * sizeof(int));
You should also do the same for arr, particularly if you use large values for n.
The program has undefined behavior because you're going out of bound of the array. This is because in your for loop condition, you're using i<=n instead of i<n.
Undefined behavior means anything1 can happen including but not limited to the program giving your expected output. But never rely(or make conclusions based) on the output of a program that has undefined behavior. The program may just crash.
So the output that you're seeing(maybe seeing) is a result of undefined behavior. And as i said don't rely on the output of a program that has UB. The program may just crash.
So the first step to make the program correct would be to remove UB. Then and only then you can start reasoning about the output of the program.
Additionally, in Standard C++ the size of an array must be a compile time constant. This means that the following is incorrect in your program.
int n;
cin >> n;
int arr[n]; //not standard C++ since n is not a constant expression
1For a more technically accurate definition of undefined behavior see this where it is mentioned that: there are no restrictions on the behavior of the program.
Segmentation fault is due to usage of memory that you don't own, or in other words stack over flow. Most likely because you're creating an array of size 1e5+2 and looping over it, initializing every element. That's not the best way to find the recurrence of an element. Instead use a map with key value pairs.

Segmentation fault in online compilers

The code below works fine in gdb and VS code but other online compilers keep throwing "segmentation fault". Can anyone please help me with this? Every question I try to solve I keep getting this error.
For example:
Given an array of integers. Find the Inversion Count in the array.
Inversion Count: For an array, inversion count indicates how far (or close) the array is from being sorted. If the array is already sorted then the inversion count is 0. If an array is sorted in the reverse order then the inversion count is the maximum.
Formally, two elements a[i] and a[j] form an inversion if a[i] > a[j] and i < j.
Code:
long long int inversionCount(long long arr[], long long N) {
vector<long long> v;
long long int count = 0;
for (int i = 0; i < N; i++) v[i]= arr[i];
auto min = min_element(arr, arr+ N);
auto max = max_element(arr, arr+ N);
swap(v[0], *min);
v.erase(max);
v.push_back(*max);
for (int i = 0; i < N; i++) {
if(v[i] > v[i+1]) {
swap(v[i],v[i+1]);
count++;
}
return count;
}
}
You have a number of problems here. For one, you try to use elements in v without ever allocating space for them (i.e., you're using subscripts to refer to elements of v even though its size is still zero elements. I'd usually use the constructor that takes two iterators to copy an existing collection (and pointers can be iterators too).
std::vector<long long> v { arr, arr+N};
Assuming you fix that, this:
v.erase(max);
... invalidates max and every other iterator or reference to any point between the element max previously pointed to, and the end of the collection. Which means that this:
v.push_back(*max);
...is attempting to dereference an invalid iterator, which produces undefined behavior.

C++ - Code crashes when trying to sort 2d vector

I'm writing a code in C++ and it's always giving the same error: Segmentation Fault, but I don't know why this is happening. I've created a small program that gives the error.
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int N = 17;
vector<vector<int>> v;
void func(vector<int>& x){
for(int i = 0; i < N; i++){
v.push_back(vector<int>(x));
}
}
int main(){
int n = 5;
vector<int> v2(n, 0);
func(v2);
cout << v.size() << endl; // prints 17
sort(v.begin(), v.end(), [&n](const auto &a, const auto &b){
for(int i = 0; i < n; i++)
if(a[i] != b[i]) return a[i] < b[i];
return true;
});
return 0;
}
The function func is supposed to do a recursive computation. I pass v2 by reference because I push and pop elements from it. When I got to a certain point in recursion, I add it to the global 2d vector v.
My code's working to every test case I tried except this one.
The fun thing is that the programs works with no error when N < 17.
The error is happening at the lambda sort. There is an 'a' that breaks the code. Even if erase the for loop, it still crashes.
I know that using global variable is bad, but in competitive programming this is a common practice.
I'm compiling with the following:
g++ test.cpp && ./a.out
My g++ version:
(Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
EDIT:
Thanks to #DrewDormann, I managed to fix it.
Just changing the return of the lambda function to false instead of true.
std::sort requires irreflexivity. From [alg.sorting] in the standard:
The term strict refers to the requirement of an irreflexive relation (!comp(x, x) for all x)
However, the lambda returns true for comp(x, x).
The fun thing is that the programs works with no error when N < 17.
It's undefined behavior. It's unlucky if it works by chance.

How to read a line in C++ [duplicate]

vector< vector<int> > resizeVector(vector< vector<int> > m)
{
vector< vector<int> > newMatrix;
int i,j;
for (i = 0; i < m[i].size(); i++)
{
for(j = 0; j < m[j].size(); j++)
{
newMatrix[i][j] = m[i][j];
}
}
return (newMatrix);
}
I am making a program that will do a whole lot of matrix manipulation, and this section is crashing and I don't exactly know why. I have narrowed it down to the line:
newMatrix[i][j] = m[i][j];
It crashes right here, and I am not sure why.
In addition to what #Saurav posted, newMatrix is empty so you cannot assign values to newMatrix[i][j]. You can fix this by initializing the vectors with a given size:
vector< vector<int> > resizeVector(vector< vector<int> > m)
{
vector< vector<int> > newMatrix(m.size());
int i,j;
for (i = 0; i < m.size(); i++)
{
newMatrix[i].resize(m[i].size());
for(j = 0; j < m[i].size(); j++)
{
newMatrix[i][j] = m[i][j];
}
}
return (newMatrix);
}
Before the for-loops we initialize newMatrix to have m.size() many empty vectors inside of it (the vectors are empty due to their default constructor). During each iteration of the outer for-loop we ensure that each vector within newMatrix has the correct size using the resize member function.
Note that if you want a copy of a vector you can simply just write:
vector< vector<int> > newMatrix(m);
Your checks are wrong. Instead it should be
for (i = 0; i < m.size(); i++) // m.size() gives the number of rows
{
for(j = 0; j < m[i].size(); j++) // m[i].size() gives the number of columns in the row
You're assigning into your new newMatrix without setting its size first. It will default to empty, and any attempt to assign to it will result in undefined behavior.
Since you don't pass in a new size, it's hard to know exactly what you're trying to accomplish. That's why I don't have more explicit advice on how to fix it.
If you want to allocate vector of vector, the you need to allocate memory for the matrix before you index on it. So you will have to use something like
newMatrix.resize(size);
for (int i = 0; i < size; ++i) {
newMatrix[i].resize(size);
}
Or you could use .push_back() vector method to add values to the vector without allocating memory beforehand.
vectors operator[] returns a reference to the specified element without bounds checking.
That means it does not magically resize the vector, or perform any other operations to ensure the element exists. If the element does not exist, the result is undefined behaviour - which means means anything can happen. Practically, it often causes the program to access an invalid memory location, which causes a crash.
The above is true even for a simple vector<int>. You've compounded your problems by working with a vector<vector<int> > (Each element of a vector<vector<int> > is a vector<int>).
Your function is actually a little breathtaking in the number of times it potentially invokes undefined behaviour. You happen to be getting a crash on the statement newMatrix[i][j] = m[i][j], but the potential for undefined behaviour actually occurs before then.
In the outer loop, m[i] will not exist if m.size() (which your code doesn't check) has a value zero. If m.size() is zero, that causes the evaluation of m[i] (as m.operator[](i)) to have undefined behaviour.
Essentially, you need to ensure any index i is valid before evaluating m[i], and then ALSO ensure that j is a valid index of m[i] before evaluating m[i][j]. And then do the same for newMatrix. Your code does none of this at all. A more correct rendering of your function (assuming the intent is to create a copy of m) is
vector< vector<int> > resizeVector(vector< vector<int> > m)
{
vector< vector<int> > newMatrix;
int i,j;
newMatrix.resize(m.size()); // necessary to ensure we can access newMatrix[i] in the loop below
for (i = 0; i < m.size(); i++) // ensure i is a valid index of m
{
// newMatrix[i].size() is still zero, so we need to resize for use in the inner loop
newMatrix[i].resize(m[i].size());
for(j = 0; j < m[i].size(); j++) // ensure j is a valid index of m[i]
{
newMatrix[i][j] = m[i][j];
}
}
return (newMatrix);
}
Now, the thing is, your code is actually recreating functionality that vector provides already. So, we could replace the body of the function quite simply with
vector< vector<int> > resizeVector(vector< vector<int> > m)
{
vector< vector<int> > newMatrix(m);
return newMatrix;
}
or even with
vector< vector<int> > resizeVector(vector< vector<int> > m)
{
return m;
}
This means your function (as I've modified it) is misnamed - it doesn't resize anything. In fact, it is rather pointless since, if the caller does this
x = resizeVector(y);
it could achieve the same effect without your function at all, simply as
x = y;
which is also more efficient (no function call, no creating copies to pass by value, etc).

Vector assignment crashing

vector< vector<int> > resizeVector(vector< vector<int> > m)
{
vector< vector<int> > newMatrix;
int i,j;
for (i = 0; i < m[i].size(); i++)
{
for(j = 0; j < m[j].size(); j++)
{
newMatrix[i][j] = m[i][j];
}
}
return (newMatrix);
}
I am making a program that will do a whole lot of matrix manipulation, and this section is crashing and I don't exactly know why. I have narrowed it down to the line:
newMatrix[i][j] = m[i][j];
It crashes right here, and I am not sure why.
In addition to what #Saurav posted, newMatrix is empty so you cannot assign values to newMatrix[i][j]. You can fix this by initializing the vectors with a given size:
vector< vector<int> > resizeVector(vector< vector<int> > m)
{
vector< vector<int> > newMatrix(m.size());
int i,j;
for (i = 0; i < m.size(); i++)
{
newMatrix[i].resize(m[i].size());
for(j = 0; j < m[i].size(); j++)
{
newMatrix[i][j] = m[i][j];
}
}
return (newMatrix);
}
Before the for-loops we initialize newMatrix to have m.size() many empty vectors inside of it (the vectors are empty due to their default constructor). During each iteration of the outer for-loop we ensure that each vector within newMatrix has the correct size using the resize member function.
Note that if you want a copy of a vector you can simply just write:
vector< vector<int> > newMatrix(m);
Your checks are wrong. Instead it should be
for (i = 0; i < m.size(); i++) // m.size() gives the number of rows
{
for(j = 0; j < m[i].size(); j++) // m[i].size() gives the number of columns in the row
You're assigning into your new newMatrix without setting its size first. It will default to empty, and any attempt to assign to it will result in undefined behavior.
Since you don't pass in a new size, it's hard to know exactly what you're trying to accomplish. That's why I don't have more explicit advice on how to fix it.
If you want to allocate vector of vector, the you need to allocate memory for the matrix before you index on it. So you will have to use something like
newMatrix.resize(size);
for (int i = 0; i < size; ++i) {
newMatrix[i].resize(size);
}
Or you could use .push_back() vector method to add values to the vector without allocating memory beforehand.
vectors operator[] returns a reference to the specified element without bounds checking.
That means it does not magically resize the vector, or perform any other operations to ensure the element exists. If the element does not exist, the result is undefined behaviour - which means means anything can happen. Practically, it often causes the program to access an invalid memory location, which causes a crash.
The above is true even for a simple vector<int>. You've compounded your problems by working with a vector<vector<int> > (Each element of a vector<vector<int> > is a vector<int>).
Your function is actually a little breathtaking in the number of times it potentially invokes undefined behaviour. You happen to be getting a crash on the statement newMatrix[i][j] = m[i][j], but the potential for undefined behaviour actually occurs before then.
In the outer loop, m[i] will not exist if m.size() (which your code doesn't check) has a value zero. If m.size() is zero, that causes the evaluation of m[i] (as m.operator[](i)) to have undefined behaviour.
Essentially, you need to ensure any index i is valid before evaluating m[i], and then ALSO ensure that j is a valid index of m[i] before evaluating m[i][j]. And then do the same for newMatrix. Your code does none of this at all. A more correct rendering of your function (assuming the intent is to create a copy of m) is
vector< vector<int> > resizeVector(vector< vector<int> > m)
{
vector< vector<int> > newMatrix;
int i,j;
newMatrix.resize(m.size()); // necessary to ensure we can access newMatrix[i] in the loop below
for (i = 0; i < m.size(); i++) // ensure i is a valid index of m
{
// newMatrix[i].size() is still zero, so we need to resize for use in the inner loop
newMatrix[i].resize(m[i].size());
for(j = 0; j < m[i].size(); j++) // ensure j is a valid index of m[i]
{
newMatrix[i][j] = m[i][j];
}
}
return (newMatrix);
}
Now, the thing is, your code is actually recreating functionality that vector provides already. So, we could replace the body of the function quite simply with
vector< vector<int> > resizeVector(vector< vector<int> > m)
{
vector< vector<int> > newMatrix(m);
return newMatrix;
}
or even with
vector< vector<int> > resizeVector(vector< vector<int> > m)
{
return m;
}
This means your function (as I've modified it) is misnamed - it doesn't resize anything. In fact, it is rather pointless since, if the caller does this
x = resizeVector(y);
it could achieve the same effect without your function at all, simply as
x = y;
which is also more efficient (no function call, no creating copies to pass by value, etc).