When I am programming in C++ and Visual Studio 2019 throws an error, it shows in which line it was encountered. But when coding with C++ when error is thrown, it does not show in which line exactly it appears. So it makes hard to debug and fix my program. Maybe there are settings that I need to adjust?
C++ error (it point to some 1501 line of installation files that weren't created by me):
vector<int> myVector(2);
cout << myVector[4] << endl;
Errors in both programs in these examples are of a same category: vector (in C++).
Without providing more code and looking at the minimal c++ code you provided:
vector<int> myVector(2);
cout << myVector[4] << endl;
It looks like you have too many elements in myVector in the second line. You will have UB because the [] operator does not allocated more elements. You only declared 2 elements.
Now, when you send your vector to cout you are saying you have 4 which is false.
That is why you are getting the error: "Expression: vector subscript out of range".
You only have two indices 0 and 1, if you define a vector with 2 elements.
Now if you were trying to see the size of your vector you use the .size() function which returns the number of elements in the vector.
vector<int> myVector(2);
cout << myVector.size() << endl;
You could even do something like this with a for loop:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> myVector(2);
std::cout << myVector.size() << std::endl;
for (int i = 0; i < 10; i++)
myVector.push_back(i);
std::cout << myVector.size() << '\n';
return 0;
}
Related
My code runs fine when I run it on online IDEs but fails with debug assertion error when run on visual studio. The error is probably in the rand() function because when I specifically use random integer values, it works just fine. I don't understand why is it not running on VS.
The following message is being displayed:
Debug Assertion Failed!
Program: [Path]
Line: 1639
Expression : sequence not ordered
Also I'd like to ask how to debug these errors as they are not specifying a particular code instance.
#include <iostream>
#include <list>
#include <cstdlib> //for rand() function
using namespace std;
void display(list <int> &lst)
{
list <int> ::iterator p;
for (p = lst.begin(); p != lst.end(); p++)
{
cout << *p << " ";
}
cout << "\n\n";
}
int main()
{
list <int> list1; //empty list of zero length
list <int> list2(5); //empty list of size 5
for (int i = 0; i < 3; i++)
{
list1.push_back(rand() % 100);
}
list <int> ::iterator p;
for (p = list2.begin(); p != list2.end(); p++)
{
*p = (rand() % 100);
}
cout << "List1: ";
display(list1);
cout << endl << endl;
cout << "List2: ";
display(list2);
cout << endl << endl;
//Add two elements at the ends of list 1
list1.push_back(200);
list1.push_front(100);
//Remove an element at the front of list 2
list2.pop_front();
cout << "Now list1: ";
display(list1);
cout << "\n\n";
cout << "Now list2: ";
display(list2);
cout << "\n\n";
list<int> listA, listB;
listA = list1;
listB = list2;
//Merging two lists(unsorted)
list1.merge(list2);
cout << "Merged unsorted lists\n";
display(list1);
cout << "\n\n";
//Sorting and merging
listA.sort();
listB.sort();
listA.merge(listB);
cout << "Merged sorted lists\n";
display(listA);
cout << "\n\n";
//Reversing a list
listA.reverse();
cout << "Reversed merged list: \n";
display(listA);
return 0;
}
merge requires that the lists be sorted (see: https://en.cppreference.com/w/cpp/container/list/merge). In your first call to merge the lists are not sorted (the lists are only sorted prior to your second call).
In debug mode, the Microsoft C++ standard libraries include extra runtime checks to enforce invariants such as this. The "Online IDE" likely uses GCC with libstdc++ or similar which generally does not include the same level of runtime checking that the Microsoft libraries do, and therefore does not catch the mistake.
Documentation of list::merge says:
Exception safety
If the allocators in both containers do not compare equal, if comp does not define a strict weak ordering, or if the container elements
are not ordered according to it, it causes undefined behavior.
Otherwise, if an exception is thrown by a comparison, the container is
left in a valid state (basic guarantee). Otherwise, if an exception is
thrown, there are no changes in the container (strong guarantee).
So depending on compiler implementation behavior can be different when merging unsorted lists. Apparently Visual Studio does extra checking in debug mode which is not required (but allowed) by C++ standard.
This question already has answers here:
Vector going out of bounds without giving error
(4 answers)
Closed 5 years ago.
I read this tutorial
std::vector beginners tutorial
and also saw this question:
similar tpoic question
Yet, when I run my simple example I did not see the excepted results, which are --> an std::out_of_range exception is NOT thrown.
Did I misunderstand here something ?
The sample code I run is the following (the code run and terminates successfully, i.e.- no exceptions thrown):
#include <iostream>
#include <vector>
using namespace std;
class MyObjNoDefualtCtor
{
public:
MyObjNoDefualtCtor(int a) : m_a(a)
{
cout << "MyObjNoDefualtCtor::MyObjNoDefualtCtor - setting m_a to:" << m_a << endl;
}
MyObjNoDefualtCtor(const MyObjNoDefualtCtor& other) : m_a(other.m_a)
{
cout << "MyObjNoDefualtCtor::copy_ctor - setting m_a to:" << m_a << endl;
}
~MyObjNoDefualtCtor()
{
cout << "MyObjNoDefualtCtor::~MyObjNoDefualtCtor - address is" << this << endl;
}
// just to be sure - explicitly disable the defualt ctor
MyObjNoDefualtCtor() = delete;
int m_a;
};
int main(int argc, char** argv)
{
// create a vector and reserve 10 int's for it
// NOTE: no insertion (of any type) has been made into the vector.
vector<int> vec1;
vec1.reserve(10);
// try to access the first element - due to the fact that I did not inserted NOT even a single
// element to the vector, I would except here an exception to be thrown.
size_t index = 0;
cout << "vec1[" << index << "]:" << vec1[index] << endl;
// now try to access the last element - here as well: due to the fact that I did not inserted NOT even a single
// element to the vector, I would excpet here an excpetion to be thrown.
index = 9;
cout << "vec1[" << index << "]:" << vec1[index] << endl;
// same thing goes for user defined type (MyObjNoDefualtCtor) as well
vector<MyObjNoDefualtCtor> vec2;
vec2.reserve(10);
// try to access the first element - due to the fact that I did not inserted NOT even a single
// element to the vector, I would except here an exception to be thrown.
index = 0;
cout << "vec2[" << index << "]:" << vec2[index].m_a << endl;
// now try to access the last element - here as well: due to the fact that I did not inserted NOT even a single
// element to the vector, I would except here an exception to be thrown.
index = 9;
cout << "vec2[" << index << "]:" << vec2[index].m_a << endl;
return 0;
}
Notes:
The sample code is compiled with -std=c++11 option.
Compiler version is g++ 5.4 (on my Ubuntu 16.04 machine).
Thanks,
Guy.
A vectors operator[] function may or may not do bounds-checking. The implementations that do have bounds-checking, typically only does it for debug-builds. GCC and its standard library doesn't.
The at function on the other hand, does have mandatory bounds-checking and will be guaranteed to throw an out_of_range exception.
What happens here is simply that you go out of bounds and have undefined behavior.
Is at() that perform the range check, not (necessarily) operator[].
Your code have udefinded behaviour.
If you want to be sure to get an exception, use
vec1.at(index)
instead of
vec1[index]
I'm trying to create a vector where each element is a multiple of 3 below 1000. I tried two ways, only one of which worked. The non-functioning way was:
int main() {
vector<int> multiples_of_three;
for (int i = 0; i <= 1000/3; ++i)
multiples_of_three[i] = 3*i;
cout << multiples_of_three[i] << "\n";
}
That gave an out of range error specifically on multiples_of_three[i]. This next bit of code worked:
int main() {
vector<int> multiples_of_three(334);
for (int i = 0; i < multiples_of_three.size(); ++i) {
multiples_of_three[i] = 3*i;
cout << multiples_of_three[i];
}
So if I defined the size of the vector I could keep it within it's constraints. Why is it that if I try and let the for loop dictate the number of elements I get an out of range error?
Thanks!
This works perfectly fine:
#include <iostream>
#include <vector>
using namespace std;
//this one is the edited version
int main() {
vector<int> multiples_of_three(334); //notice the change: I declared the size
for (int i = 0; i <= 1000 / 3; ++i){
multiples_of_three[i] = 3 * i;
cout << multiples_of_three[i] << "\n";
}
system("pause");
}
Consider these two examples below:
//=========================the following example has errors =====================
int main() {
vector<int> multiples_of_three;
multiples_of_three[0] = 0; // error
multiples_of_three[1] = 3; // error
cout << "Here they are: " << multiples_of_three[0]; cout << endl;
cout << "Here they are: " << multiples_of_three[1]; cout << endl;
cout << endl;
system("pause");
return 0;
}
//============================the following example works==========================
int main() {
vector<int> multiples_of_three;
multiples_of_three.push_back(0);
multiples_of_three.push_back(3);
cout << "Here they are: " << multiples_of_three[0]; cout << endl;
cout << "Here they are: " << multiples_of_three[1]; cout << endl;
cout << endl;
system("pause");
return 0;
}
So unless, you have declared the size, never use indices directly for assigning values (as in the first example). However, if the values have already been assigned, you can use indices to retrieve the values (as in the 2nd example). And in case, You want to use indices to assign values, first declare the size of the array (as in the edited version)!
the default constructor (that is called here: vector<int> multiples_of_three;) creates an empty vector. you can populate them with push_back or better if you know the number of objects you have to add, pass that number to the constructor, so it reserves the required amount of memory at once instead of constantly growing (that means allocating memory and copying the old menory into the new) the vector.
another alternative is to call reserve from the empty default contructed vector and use push_back to populate it. reserve reserves enough memory to keep the required amount of objects but without changing the size of the vector. advantage of reserve is that the default constructor is not called for every object (as it will be done with resize or parameterized constructor) that would be not necessary since you overwrite the the object in your initialization loop right after the creation of the vector.
You need to use push_back() rather than add via the indexer.
The indexer can be used for read/write access to a vector only within the bounds.
A vector doesn't magically grow in size because you use []. It started out with 0 elements in the first example and you never grew it.
Today I try something like this in VS2012 and Max OS 10.7
vector<int> vec;
vector<int> vec2;
for(int i = 0;i < 100 ;i++){
vec.push_back(i);
}
cout << "size: " << vec.size() << endl;
cout << "capacity: " << vec.capacity() << endl;
cout << vec[127] << endl;
//vec2.reserve(10);
fill_n(vec.begin(),128,-1);
cout << vec[127] << endl;
return 0;
as we know the size of vector is the real number of elements in the container, the code above can cause runtime error in VS2012, but it works fine on Max OS, and I try it in Ideone.com and also run successfully, I am not sure if something wrong with the definition of size and capacity, why I can access element out of size?
PS: the capacity at this situation on my computer is 141 on VS2012 and 128 on Mac OS and Ideone.com
std::vector operator [] won't throw any out of range error. It's a undefined behaviour to access element greater than the vector size using [] operator.
Use std::vector::at instead, which throws std::out_of_range
Bump into this problem, I try to elaborate the answer from #P0W.
#1 Access element(s) of the 2d vector
If someone wants to access the elements of the 2d vector,
one should do the following and aware of the API 2dvector.at(row#).at(col#)
#include <vector>
#include <iostream>
using namespace std;
int main() {
vector <vector<int> > vi;
vi.push_back( vector <int>() ); // add empty 1d vector
vi.at(0).push_back( 1 ); // push 1st element
cout << vi.at(0).at(0) << endl; // access element of 2d vector and prints 1
vi.at(0).at(0) = 2; // change number
cout << vi.at(0).at(0) << endl; // access element of 2d vector and prints 2
}
#2 std::out_of_range
if you have difficulty finding the example of std::out_of_range, here is one
example code
// out_of_range example
#include <iostream> // std::cerr
#include <stdexcept> // std::out_of_range
#include <vector> // std::vector
int main (void) {
std::vector<int> myvector(10);
try {
myvector.at(20)=100; // vector::at throws an out-of-range
}
catch (const std::out_of_range& oor) {
std::cerr << "Out of Range error: " << oor.what() << '\n';
}
return 0;
}
output
Out of Range error: vector::_M_range_check
I have some difficulties in understanding the behaviour of the C++ clear function, when applied to a vector.
I tried to compile and run the following function:
#include <iostream>
#include <vector>
using namespace std;
int main ()
{
unsigned int i;
vector<int> myvector;
myvector.push_back (1);
myvector.push_back (2);
myvector.push_back (3);
cout << "myvector contains:";
for (i=0; i<myvector.size(); i++) cout << " " << myvector[i];
myvector.clear();
myvector.push_back (11);
myvector.push_back (12);
cout << "\nmyvector contains:";
for (i=0; i<myvector.size(); i++) cout << " " << myvector[i];
cout << endl;
cout << " entry3 = " << myvector[2]<<endl;
return 0;
}
And this is the output:
myvector contains: 1 2 3
myvector contains: 11 12
entry3 = 3
How is it possible that the information of the third entry of the vector has not been erased when clearing the vector?
From the docs:
All the elements of the vector are dropped: their destructors are called, and then they are removed from the vector container, leaving the container with a size of 0.
Basically you're invoking undefined behavior on myvector[2] because that item no longer exists. You only pushed 2 elements in the vector after calling clear(), so only indices 0 and 1 are accessible.
You're unlucky that it didn't crash, because appearing to work can hide bugs. There's no guarantee that the value is erased.
Trying to access the element with .at(2) instead will result in an exception being thrown (operator[]() doesn't do any bound-checking, whereas at() does).
If you attempt to run this code in debug mode, it's likely it will crash with a debug assertion. Referencing past the end of an array is undefined behaviour.
What's actually happening is that vector has not wiped the memory it was previously using before you ran clear(). This memory is still present but it's not defined what will happen if you access it. It's up to you to perform bounds checking to avoid running off the end of a vector. You can do this by looping with size() as a bounds, or by using at() and catching the out_of_range exception. I wouldn't particularly recommend this latter approach since it's not a good idea to use exceptions for runtime checks.