Segmentation Fault in C++ - Vectors - c++

#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int a, b;
cin>>a;
vector<int> numbers;
for(int i=0; i<a; i++)
{
cin>>b;
numbers.push_back(b);
}
int c,d,e;
cin>>c;
numbers.erase(numbers.begin()+c-1);
cin>>d>>e;
numbers.erase(numbers.begin()+d-1, numbers.end()+e);
cout<<numbers.size();
for(int x : numbers)
cout<<x<<" ";
return 0;
}
Hello everyone,
I am learning c++ and writing a very simple program, but this code is giving "Segmentation Fault" as error. I really could not figure out why this is happening.
Thank you.

This line
numbers.erase(numbers.begin()+d-1, numbers.end()+e);
cannot be correct. Incrementing the end iterator never gets you a valid iterator. It is not quite clear what you want to do, but if you want to erase elements in the range of indices [d,e) then that would be
numbers.erase(numbers.begin()+d, numbers.begin()+e);
Note: No +1 needed on the first, because the first is inclusive. And you get an iterator to the e-th element by incrementing the begin iterator not the end iterator (well... I assume the common 0-based counting, ie the "first" element is the 0th element ;).
Also, as mentioned in comments, you should check if the user entered values are in range, before calling erase. erase does no bounds-checking. If you pass invalid iterators your get undefined behavior.

Related

std::transform behaviour along with back_inserter not understanding

I have a trouble in understanding the behaviour of transform function if used with back_inserter.
#include <algorithm>
using namespace std;
int main()
{
vector<int> a{1,2,4};
transform(begin(a), end(a), back_inserter(a), [](auto e){ cout << e << "-" ;
return e;});
return 0;
}
In the above program, I get the output as 1-0-4. I am not able to understand how this 0 is coming?
Please see live example cpp.sh/6vpzk
This code does vector::push_back while iterating over it using its iterators. vector::push_back invalidates all existing iterators causing undefined behaviour, and that is where that 0 comes from (it can be any other number, since the behaviour is undefined).
You should probably use for_each or range for loop.

Iterator confusion using maps

sorry because this question isn't really advanced, but I am having lots of trouble understanding why this program works the way it does.
#include <iostream>
#include <fstream>
#include <set>
#include <vector>
#include <map>
using namespace std;
int main() {
ofstream fout("castle.out");
ifstream fin("castle.in");
map<int, int, greater<int> > cnt;
map<int, int, greater<int> >::iterator x;
x = cnt.begin();
cnt[1] = 0;
cnt[2] = 7;
fout << x->first; //This outputs 2
x++;
fout << x->second;//This outputs 2 again, why not 0?
return 0;
}
So I defined a map called cnt, and then made an iterator for it x. I ordered it by greatest integer to least greatest integer. I set that iterator equal to x.begin(), and then I outputted the value of x, using first. But then I wanted to output the value 0, so I did one x++; and then tried to output the value of x->first. The idea behind this was that the iterator would increase by one and point to the next pair in my map, so then it would point to 1, which comes after the 2.
Why does it not work and give me 2 again?
I realized that if I do this instead:
x++;
x++:
fout << x-> first;
with two x++, I will have the value 1. Why is this? Thanks!
Your code has undefined behavior.
x = cnt.begin();
Sets x to begin() while the container is empty which effectively gives you the end() iterator. Since std::map::operartor[] doesn't invalidate any iterators you still have an end() iterator and dereferencing it is undefined behavior.

Producing permutations of a set of integers in C++. Getting Segmentation Fault

I was trying to solve a problem which involved producing all the permutations of a set of numbers. The idea seemed simple enough (code below), but I keep getting segmentation faults. Can anyone tell me what I'm doing wrong?
void permute(set<int>& s, vector<int>& v) {
if(s.empty()) {
// read the permutation in v.
return;
}
set<int>::iterator i;
for(i = s.begin(); i != s.end(); i++) {
int x = *i;
s.erase(i);
v.push_back(x);
permute(s, v);
v.pop_back();
s.insert(x);
}
}
To produce all permutations in C++ use std::next_permutation. The problem here is that you cannot permutate the set, because the ordering is preset by the key comparator operator (in your case the less than operator). What you can do is store your values in a non associative container and then have a go.
#include <set>
#include <algorithm>
#include <iterator>
#include <vector>
using namespace std;
void permut(std::set<int> const &inp, std::vector<int> &all_permutations)
{
vector<int> tmp(inp.size());
copy(inp.begin(), inp.end(), tmp.begin());
vector<int> all_permutations;
do
{
copy(tmp.begin(), tmp.end(), back_inserter(all_permutations));
} while (std::next_permutation(tmp.begin(), tmp.end()));
}
The permute() function calls itself recursively while iterating over the mutable containers and making changes. This violates iterator validity promises.
You might try something based on std::next_permutation()
I have not gone into the precise behaviour you can expect from a set, but it seems pretty clear that the things you are doing inside the for loop are enough to make the iterator invalid. I would suggest redesigning things so that you have two sets, and work through one (which starts off full) while generating the permutation in the other (which starts off empty).

Segmentation fault while initializing vector by an initialized array in C++

I wanted to use the sort() in the algorithm library in C++. I could find examples for sorting vectors only, thus I am trying to initialize a vector by an initialized array. When executing I am getting a segmentation fault and couldn't figure out what is wrong here in the code I wrote.
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int n,k,packet[1000],min=0;
scanf("%d",&n);
scanf("%d",&k);
for (int i = 0; i < n; ++i)
{
scanf("%d",&packet[i]);
cout<<i<<endl;
}
cout<<"debug";
vector<int> packets(packet,packet+n);
vector<int>::iterator start,stop;
sort(packets.begin(),packets.begin()+n);
min=*(packets.begin())- *(packets.end());
cout<<min;
for (vector<int>::iterator it=packets.begin(); it!=packets.end()-k; ++it)
{
printf("%d ",*it );
if((*(it+k) - *it)<min)
{
start=it;
stop=it+k;
}
}
printf("%d\n",*stop- *start );
return 0;
}
*(packets.end())
packets.end() returns an iterator to the element, following the last element of the vector.
Attempting to derefenrence it causes Undefined Behavior.
The comments explain that you can use sort with an array just fine (if you look at http://en.cppreference.com/w/cpp/algorithm/sort you'll see that sort takes two arguments that: -RandomIt must meet the requirements of ValueSwappable and RandomAccessIterator.. Plain pointers fulfill this requirement).
In your example, the segfault happens because you try to dereference a valid but undereferencable iterator (the iterator returned by 'end()' in: min=*(packets.begin())- *(packets.end());. Basically it returns an iterator that points to after the last element of the vector. If you want to get an iterator to the last element, you can use rbegin() but of course you need to make sure that the vector is not empty first).
You could have seen this quite easily by running your code under a debugger, you'd see that the segmentation fault had nothing to do with the call to sort

string s; &s+1; Legal? UB?

Consider the following code:
#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
string myAry[] =
{
"Mary",
"had",
"a",
"Little",
"Lamb"
};
const size_t numStrs = sizeof(myStr)/sizeof(myAry[0]);
vector<string> myVec(&myAry[0], &myAry[numStrs]);
copy( myVec.begin(), myVec.end(), ostream_iterator<string>(cout, " "));
return 0;
}
Of interest here is &myAry[numStrs]: numStrs is equal to 5, so &myAry[numStrs] points to something that doesn't exist; the sixth element in the array. There is another example of this in the above code: myVec.end(), which points to one-past-the-end of the vector myVec. It's perfecly legal to take the address of this element that doesn't exist. We know the size of string, so we know where the address of the 6th element of a C-style array of strings must point to. So long as we only evaluate this pointer and never dereference it, we're fine. We can even compare it to other pointers for equality. The STL does this all the time in algorithms that act on a range of iterators. The end() iterator points past the end, and the loops keep looping while a counter != end().
So now consider this:
#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
string myStr = "Mary";
string* myPtr = &myStr;
vector<string> myVec2(myPtr, &myPtr[1]);
copy( myVec2.begin(), myVec2.end(), ostream_iterator<string>(cout, " "));
return 0;
}
Is this code legal and well-defined? It is legal and well-defined to take the address of an array element past the end, as in &myAry[numStrs], so should it be legal and well-defined to pretend that myPtr is also an array?
It is legal and not UB to have a pointer to "one past the end" of an array, and any single object can be treated as if it were in an array of length 1; however, you need to use ptr + 1 instead due to the technicality of &ptr[1] dereferencing and then taking the address. This also applies to &array[size] becoming array + size.
What you have will work as you expect on all platforms of which I'm aware, but given how easy it is to use the unambiguously correct form, I see no reason not to do that instead.
The C++ standard in 5.6/4 "Additive operators" says:
For the purposes of these operators, a pointer to a nonarray object behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type.
The C99 standard 6.5.6/7 says essentially the same.