This is the first part of a function I have that's causing my program to crash:
vector<Student> sortGPA(vector<Student> student) {
vector<Student> sorted;
Student test = student[0];
cout << "here\n";
sorted.insert(student.begin(), student[0]);
cout << "it failed.\n";
...
It crashes right at the sorted part because I can see "here" on the screen but not "it failed." The following error message comes up:
Debug Assertion Failed!
(a long path here...)
Expression: vector emplace iterator outside range
For more information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.
I'm not sure what's causing the problem now, since I have a similar line of code elsewhere student.insert(student.begin() + position(temp, student), temp); that does not crash (where position returns an int and temp is another declaration of a struct Student). What can I do to resolve the problem, and how is the first insert different from the second one?
It should be:
sorted.insert(sorted.begin(), student[0]);
You were passing the iterator from the wrong instance.
When you use std::vector::insert ( iterator position, const T& x );, the iterator position must point into that same vector. You're using an iterator from student with sorted.insert, which dies.
Related
I have to write a function that erases an element out of the list if it's bigger than the previous element.(The previous element is the one which points to the next element before deletion)
I think I've basically finished it but I don't know why it doesn't erase 5 out of my list.
void deleteBigger(list<int> s){
list<int>::iterator test;
for(test = s.begin(); test != s.end(); test++){
int sk1=*test;
cout<<sk1<<endl;
test--;
int sk2=*test;
cout<<sk2<<endl;
if(sk1>sk2){
cout<<"Im here!\n";
s.erase(test);
}
test++;
}
}
It doesn't give an error or anything it just doesn't erase. I tried to test the erase method in the main function of the program, and there it worked fine.
There are three problems with your code:
Your list is passed by value, not reference. So you are changing a copy of your list and it doesn't alter the original container
You try to remove an element from a list while iterating it. Edit: As #Remy Lebeau mentioned in the comments, to be more precise it's a problem because you don't update the iterator properly, but not a problem on its own. Be advised, that when you remove an element from a list, the iterator which pointed to the erased element is considered invalidated.
Upon the first iteration, you decremented the iterator out of the container's bounds
Summing it up, what you might want to have here looks something like this:
void deleteBigger(std::list<int> &s) {
using namespace std;
if (s.empty()) {
return;
}
for(auto test = next(s.cbegin()); test != s.cend(); ++test){
while ((*test > *prev(test)) && (test != s.cend())) {
test = s.erase(test);
}
}
}
I've copied your code and it doesn't work. The problem is your iterator pointer "test". You can't degree a pointer at the begin. The only thing you can do is use a control.
Note: it's wrong decrement a pointer because you are decrementing of (32 bits) the index of memory. In this case there is overriding -- operator that saves your program but be careful next times
Control your program. It's important use a debugger editor where you can stop the program at certain point and control the value of the variables
While writing code for my assignment, I have stuck on one strange behavior. The code is big, so while it is not necessary, I won't post it.
The thing is while I was trying to delete an object from the vector, I had a segmentation fault. While trying to debug it myself, I have found this:
If I execute my code with the following snippet, I have my vector empty and then segmentation fault on the second line (since vector is empty).
cout << this->adjacencyList.empty() << endl; // yeah, I'm working with graph
cout << *(this->adjacencyList[0]) << endl; // list has pointers
However, when I delete the second line, it shows that vector is not empty and then proceeds.
The guard for empty vectors cannot hold it and segmentation fault comes.
Do you have any ideas on this behavior? If the point is still vague, I can post my full code as an edit.
Thanks in advance.
EDIT:
For the one who was asking "a little more".
void Node :: removeEdge (string destination) // removes an edge; edge is a class that contains a pointer to another node and its weight
{
bool deleted = false;
cout << *this << endl; // output stream operator is overloaded for node class and is working properly - shows it's label and edges - no error for an edge
cout << this->adjacencyList.empty() << endl;
// cout << *(this->adjacencyList[0]) << endl; // output stream operator is overloaded for edge class - error for an edge
if (!this->adjacencyList.empty())
{
for (vector <Edge *> :: iterator itr = this->adjacencyList.begin(); itr != this->adjacencyList.end(); ++itr)
{
if (((*itr)->getAdjacent())->getLabel() == destination) // segfault here
{
Edge *temp = *itr;
this->adjacencyList.erase (itr);
delete temp;
deleted = true;
}
}
}
if (!deleted)
throw EDGE_DOES_NOT_EXIST; // one of exceptions declared in enum somewhere in my code
}
SECOND EDIT:
NOTE: I cannot change headers (they were supplied by assistants), so don't ask me to change.
If you are interested in a full code, you can find here
http://pastebin.com/iCYF6hdP - Exceptions.h - all exceptions
http://pastebin.com/1fcgHGDa - Edge.h - edge class declaration
http://pastebin.com/C2DD6e3D - Edge.cpp - edge class implementation
http://pastebin.com/ZNqQ1iHE - Node.h - node class declaration
http://pastebin.com/kaVtZ3SH - Node.cpp - node class implementation
http://pastebin.com/A7Fwsi4m - Network.h - graph class declaration
http://pastebin.com/02LX0rjw - Network.cpp - graph class implementation
http://pastebin.com/MRMn0Scz - main.cpp - sample main
I would guess, that the pointer stored in the first element of your vector is invalid (perhaps NULL?).
So the segfault doesn't come up in this->adjacencyList[0] but in *(some_invalid_pointer).
Try
Edge* firstEdge = this->adjacencyList[0];
cout << *firstEdge << endl;
to verify this.
EDIT
If the segfault happens in the first statement (the assignment), this means, that either this is invalid or you somehow managed to corrupt memory belonging to the internals of vector. For this to verify, we would have to see all code that deals with your adjacencyList (and I'm not sure if SO people have the time for this task ...)
Note
I've spotted a bug in the removeEdge, which is not directly related to your problem. Within the loop, you use vector::erase to delete the current element. This invalidates all iterators beyond the current one, so theoretically the rest of the loop is the infamous 'undefined behavior'(TM). In this specific case (and supposing a 'normal' standard library), this will not result in a segfault but you might miss some elements:
If you delete the current element, the current iterator (normally simply a pointer) will point to the next element. Then, the loop increment will move it to the element after this one resulting in one element not being checked.
If you have similar bugs in your code in other places, this might well result in memory corruption.
Tip
If you're using Microsoft C++, you can enable checked iterators (see here). These might be able to spot this kind of bugs in your code.
2nd EDIT (in response to code)
You have a serious error in the Node::operator+.
Node &operator+ (Node &l, Node &r) // merges two nodes - for network merging
{
Node newNode (l.label);
// Doing something
return newNode;
}
That means, you're returning a reference to a local variable, never do that :) ...
Note that, since you're using a vector of pointers, which are managed separately and released in the destructor, you cannot simply change the signature to Node operator+(...: in this case, the standard copy constructor would be called, which would simply copy all pointers to the result object. Then, the destructor of the local object would be called which would invalidate all pointers.
To fix this, you should implement a copy constructor on Node which makes real copies of all edges in the adjacency list.
Alternatively, you could use smart pointers (either auto_ptr resp. unique_ptr or shared_ptr) for the list.
Or you change the merge function to something like Node::mergeFrom(Node& node2) instead of overloading the +operator.
Concerning the original problem, you can easily end up working on an invalid Node instance using your current code (so the *this-Pointer would be invalid inside removeEdge)
void insert_string( std::vector<std::string> & strings, const std::string &s )
{
std::vector<std::string>::iterator it=lower_bound(strings.begin(),strings.end(),s);
if(strings.size()>0) std::cout<<*it<<" is found\n"; // ****
strings.insert(it,s);
}
When attempting to use this function, the first insertion goes fine. The second insertion will output "[firststring] is found" and then segfault. If I comment out the if/cout line, I can repeatedly call and no segfaults occur.
I've also tried doing something like std::string tmp=*it; which will then segfault on that line. While printing is not a huge deal, what I'm really trying to do is check if the string at the position found by lower_bound is the same as the string that is trying to be inserted (i.e., if(*it==s), which is segfaulting just like the above two examples).
What am I missing here?
Thanks!
Check for the condition if it == strings.end(), if it is don't print it. This could cause the issue. Are you sure the string you're trying to check is in the vector of strings?
In my code, I have a vector <vector <vector <vector <std::tr1::shared_ptr<foo> > > > > named foosBoxes. The nested vector has a role of simulating a physical boxes position. I also have a while loop which cause a segmentation fault:
vector<std::tr1::shared_ptr<foo> >::iterator fooit = foosBoxes[x][y][z].begin(); //x,y,z are valid integer
std::tr1::shared_ptr<foo> aFoo;
while (fooit != foosBoxes[x][y][z].end()){
aFoo = *fooit; //this cause segmentation fault
fooit++;
//some stuff which does not have an effect on fooit;
}
Some thing I have tried:
1. I have tried to use aFoo = *fooit++ but this didn't work.
2. The segmentation fault occurs roughly after several thousandths loops which went on fine.
3. I have tried to valgrind the problem and valgrind went through the step.
4. In the loop that crashes, I have printed a running counter before and after the suspected line. when before the line, I get 8 printings (the size of the vector) and when after I get 7 printings.
How can I figure this out?
Update:
I have added a loop to run before the main loop:
int kkk = 1214
int c = 0;
while (c < foosBoxes[x][y][z].end()){
aFoo = foosBoxes[x][y][z][c++];
printf("%i\t, kkk);
fflush(stdout);
}
Which yields the same results.
Update:
according to gdb:
Program received signal SIGSEGV, Segmentation fault.
0x000000000043e400 in rotate (kkk=1214) at
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/tr1/boost_shared_ptr.h:153
153 dispose();
I think that the appropriate function in boost_shared_ptr.h is
void
release() // nothrow
{
if (__gnu_cxx::__exchange_and_add(&_M_use_count, -1) == 1)
{
dispose(); //this is line 153
#ifdef __GTHREADS
_GLIBCXX_READ_MEM_BARRIER;
_GLIBCXX_WRITE_MEM_BARRIER;
#endif
if (__gnu_cxx::__exchange_and_add(&_M_weak_count, -1) == 1)
destroy();
}
}
dispose() is defined elsewhere in the file:
// dispose() is called when _M_use_count drops to zero, to release
// the resources managed by *this.
virtual void
dispose() = 0; // nothrow
Could it be that the reason is ill management of shared_ptr and I should switch back to regular pointer?
Update:
yet another test with similar result:
int kkk = 1214
int c = fooBoxes[x][y][z].size();
while (c >= 0){
aFoo = foosBoxes[x][y][z][c--];
printf("%i\t, kkk);
fflush(stdout);
}
This time the program crush in the third iteration. Should the problem was with wrong allocation, then the program should have crush in the first iteration (in the opposite direction the program crashes in the first iteration).
Run your code with libstdc++ in debug mode. It will do extra checks of iterators, containers and algorithms and hopefully will help to find the bug.
//some stuff which does not have an effect on fooit;
But does the stuff have any effect on foosBoxes[x][y][z]?
In particular does it remove elements or cause a vector relocation? If so, fooit cannot be compared meaningfully to foosBoxes[x][y][z].end().
Also, what happens to aFoo in the loop? If this gets an invalid value, an assignment to it later will cause undefined behaviour.
Try removing the some stuff from the loop. If that works the stuff contains a bug. If the loop still fails, the cause must be an invalid value in fooxBoxes[] before you enter the loop
I have no experience with ValGrind. But I have used similar products. Please check that you have configured ValGrind to its most strict settings. This might make using it painfully slow, but hopefully finds the bug.
You're code as it is looks okay, the only thing I can think is that are x y z valid? operator[] does no bounds checking...
I have came to the conclusion that the problem was with the use vector is wrong since I update it through the code. I don't know how the memory management in c++ works but I believe that some sort of overlapping between two vector occurred. I have switched to set and everything works now
To operate on an element of foosBoxes[x][y][z] you can also try:
while (fooit != foosBoxes[x][y][z].end()){
vector<std::tr1::shared_ptr<foo> > *aFoo = *fooit;
fooit++;
//To use the object
// use it as aFoo->method()
}
Not sure if i am making the point. But i am currently using pointers to iterate in my objects.
I want to erase an element from a vector in c++, but it shows a runtime assertion error.
My code is:
int i=0;
for(socketIterator=vectClientSocket.begin();socketIterator!=vectClientSocket.end();){
SOCKET clientSocket=*socketIterator;
isTrue=getBufferData(strt,stp,rm,clientSocket);
if(!isTrue){
vectClientSocket.erase(vectClientSocket.begin()+i);
vector<RMLObserver*>::iterator it;
for(it=vectRMLObserver.begin();it<vectRMLObserver.end();it++)
{
RMLObserver *observer = (RMLObserver*)*it;
observer->infosetSent(info->getRMLThinTranskportToken());
}
}
else
++socketIterator;
i++;
}
When one element is removed it shows a runtime error,
Please help me...thank you in advance.
You need to update your iterator after erasing an element:
socketIterator = vectClientSocket.erase(socketIterator);
see also std::vector<..>::erase(..) documentation
[EDIT]
Use the operator !=(..) to compare the iterators:
for(socketIterator=vectClientSocket.begin();socketIterator!=vectClientSocket.end();){
After this line:
vectClientSocket.erase(socketIterator);
socketIterator is an invalid iterator because where it used to point has been erase. Between this line and the next iteration through your loop you never give it a valid value so this line in the next iteration is an invalid dereference.
SOCKET clientSocket=*socketIterator;
As Simon points out, even before this, the loop condition socketIterator<vectClientSocket.end() will also cause undefined behavior as socketIterator is no longer a valid iterator into vectClientSocket.