vector<bool> erase iterator outside range expression

i am writing a rather simple program for huffman encoding and cant find out why this: "expression:vector<bool> erase iterator outside range" keeps appearing.
I have tested each part of the code separately and it works fine and started testing the methods in groups and found that the fault is in the following function:

.cpp
1
2
3
4
5
6
7
8
9
10
11
12
 void huffman_encoder::compressor::encode_characters(Node *root) {
	if (root->_left != NULL) {
		_character_code.push_back(0);
		encode_characters(root->_left);
	}
	if (root->_right != NULL) {
		_character_code.push_back(1);
		encode_characters(root->_right);
	}
	if (root->_character) { _character_table[root->_character] = _character_code; }
	_character_code.pop_back();
}


.h
1
2
3
/*in private access of class compressor*/
std::vector<bool> _character_code;
std::map<char, std::vector<bool> > _character_table;


Note:the root of the huffman tree that is passed to the function as a parameter "root" creates a correct tree and has been tested separately (works perfectly).
And no other functions use the parameters "_character_code" and "_character_table" and moreover are encapsulated from having access to these parameters so nothing outside the function above can manipulate them or the vector erase iterator.
Where exactly is your debugger telling you it encounters the problem?

Be careful of using erase with vector iterators, you may be invalidating the iterator you're trying to use.

happens in vc\include\vector in line:2829 my code doesn't have that much lines and i have not used erase at all only push_back or pop_back
What do you think pop_back() is doing?

The line you pointed out is in the include file, you need to backtrace until you are somewhere in your code.

happens in vc\include\vector in line:2829

That's the runtime code for vector.

i have not used erase at all

vector::erase is implicitly called by vector::pop_back to remove the last element.

What happens root->left and root->right are both NULL? Presumably this would happen at the end of each branch of your tree. If both ->left and ->right are NULL, you skip lines 3 and 7. When you get to line 11, the _character_code vector is empty (nothing was pushed). You can't pop_back() from an empty vector.

Thank you so much for helping me find the problem! i was trying to fix it 3 hours.. and read a ton of material on why and when the expression happens yet with no success,, until you came in.
so i have modified the code line 11 from:
 
_character_code.pop_back();


to :
1
2
3
if (!_character_code.empty()) {
		_character_code.pop_back();
}


is it a good way to do so? or is there another way you would of recommend over it ?
(with this replacement it now works!)
now when i want to view its contents with this function:
1
2
3
4
5
6
void huffman_encoder::compressor::test() {
	std::map<char, std::vector<bool> >::iterator test_itr;
	for (test_itr = _character_table.begin(); test_itr != _character_table.end(); test_itr++) {
		std::cout << test_itr->first << ":" << test_itr->second << std::endl;
	}
}


it doesnt let me print test_itr->second and says this:

Error C2679 binary '<<': no operator found which takes a right-hand operand of type 'std::vector<bool,std::allocator<_Ty>>' (or there is no acceptable conversion) Huffman_compressor c:\users\user\documents\visual studio 2015\projects\huffman_compressor\huffman_compressor\file_compressor.cpp 6

NOTE:I FIXED AND POSTED IT IN A COMMENT BELLOW
Last edited on
You're trying to print a vector not a single element unless you have overloaded the output operator<< to print each element of the vector<bool>.

This won't solve the current issue, but have you considered using the "new" range based loop instead of the iterator notation?
1
2
3
4
5
6
7
for(auto& itr : _character_table)
{
    std::cout << itr.first << " : " ;
    for(auto& it : itr.second)
        std::cout << it << " "; // Print out the vector<bool> elements.
    std::cout << std::endl;
}


well i still dont know how to use auto il overload operator << its not a problem
What don't you understand about using the ranged based loops? They greatly simplifies using iterators as shown in my snippet. By the way my snippet should properly print out your _character_table.

The auto keyword, since C++11, tells the compiler to automatically detect the proper type using type deduction.

For example:

1
2
3
auto i = 650; // Should automatically detect that i is an integer.
auto j = 6.5; // Should automatically detect that j is a double.
auto k = 6.5f; // Should automatically detect that k is a float, because of the 'f' specifier. 
closed account (E0p9LyTq)
Range-based for statements (and static assert):
http://www.learncpp.com/cpp-tutorial/b-3-range-based-for-statements-and-static_assert/

Range based for loops are a very powerful C++11 tool, you should learn to use them.

C++11 added some new data types you might want to look at:

Long long, auto, decltype, nullptr, and enum classes
http://www.learncpp.com/cpp-tutorial/b-2-long-long-auto-decltype-nullptr-and-enum-classes/
Last edited on
i finally managed to solve the problem with printing the contents as they are in a map (char,std::vector<bool>) and wanted to post the code so that other people who come across the problem can modify it for their needs:

1
2
3
4
5
6
7
8
9
10
11
void huffman_encoder::compressor::test() {
	std::map<char, std::vector<bool> >::iterator test_itr;
	std::vector<bool>::iterator i;
	for (test_itr = _character_table.begin(); test_itr != _character_table.end(); test_itr++) {
		std::cout << test_itr->first << ":";
		for (i = _character_table[test_itr->first].begin(); i != _character_table[test_itr->first].end(); i++) {
			std::cout << (*i);
		}
		std::cout << std::endl;
	}
}


Note: overloading operator << isn't needed with this method.

+ thanks for the links above il look into them as soon as i finish my current project
Last edited on
Topic archived. No new replies allowed.