try/catch missing vector subscript out of range (debug assertion failed) - c++

I have some code, where I'm using std::forward_list
Part of my code tests for vector subscripts being out of range, as well as if the element in the vector has certain properties (in this case, is not -1).
When I have just the first or second node of the list, it works fine and I can catch the error, as that's just a normal part of the program. However, on the next loop around, when I have 3 elements in the list, I get the vector subscript out of range debug assertion, and it isn't caught by my try/catch. Is there a different technique I must use to resolve this error?
Here's a snippet of the code, where it's problematic:
for(int i = 0; i < 8; i++)
{
if(curr->moves[i].at(0) >= 0 && curr->moves[i].at(1) >= 0)
{
next->setPos(curr->moves[i].at(0),curr->moves[i].at(1)); //just sets values of a vector
next->setMoves(); //sets values of a 2d vector
for(int j = 0; j < 8; j++)
{
try{if(board.kBoard[next->moves[i].at(0)][next->moves[i].at(1)] != -1) //the debug assertion is thrown here, but I cannot catch it
next->moves[i].at(2) = 1;}
catch(out_of_range const &err)
{next->moves[i].at(2) = 1;}
}
...
}
}
I've commented where the issue occurs. You'll (at least on my screen) have to scroll to the right to see it. I believe that, potentially, I can use another catch statement, but I don't know which error to use, given that I'm already using out_of_range, which normally would handle this issue. A screenshot of what the error looks like when it's thrown is this. To be completely clear, the issue occurs at try{if(board.kBoard[next->moves[i].at(0)][next->moves[i].at(1) != -1), where I have commented. It doesn't go to the catch statement at all, I think because it's using _DEBUG_ERROR()

While, theoretically, a try/catch statement could catch the error here, it isn't wise to intentionally cause errors as part of an algorithm; try/catch should be used to report when errors happen. In this case, I should have used:
if(next->moves[i].at(0) >= 0 && next->moves[i].at(1) >= 0) //1
if(board.kBoard[next->moves[i].at(0)][next->moves[i].at(1)] != -1) //2
next->moves[i].at(2) = 1; //3
else
next->moves[i].at(2) = 1; //3
This allows me to check if the subscript is out of range (1), check if an element of the board is not -1 (2), and set moves[i].at(2) to 1, in those cases (3).
This avoids any out_of_range errors, obviating the need for try/catch entirely.

Related

C++ time limit exceeded when it doesn't even execute the function

While I was solving a problem in LeetCode, I found something very strange.
I have this line which I assume gives me a time limit exceeded error:
s.erase(i-k, k);
when I comment(//) this line, it doesn't show me time exceed error, but the strange part was, it has never executed even when i didn't comment it.
below is the entire code.
and Here is the problem link.
class Solution {
public:
string removeDuplicates(string s, int k) {
char prev = s[0];
int cnt = 1;
cnt = 1;
for(int i = 1; i < s.size() + 1; i++){
if(s[i] == prev){
cnt++;
} else {
if(cnt == k){
// when input is "abcd" it never comes to this scope
// which is impossible to run erase function.
s.erase(i-k, k);
i = 0;
}
if(i >= s.size()) break;
cnt = 1;
prev = s[i];
}
}
return s;
}
};
When Input is "abcd", it never even go to the if scope where 'erase' function is in.
Although 'erase' function never run, it still affect on the time complexity, and I can't get the reason.
Does anyone can explain this? or is this just problem of LeetCode?
Many online contest servers report Time Exceeding when program encounters critical error (coding bug) and/or crashes.
For example error of reading out of bounds of array. Or dereferencing bad (junk) pointers.
Why Time Exceeded. Because with critical error program can hang up and/or crash. Meaning it also doesn't deliver result in time.
So I think you have to debug your program to find all coding errors, not spending your time optimizing algorithm.
Regarding this line s.erase(i-k, k); - it may crash/hang-up when i < k, then you have negative value, which is not allowed by .erase() method. When you get for example i - k equal to -1 then size_t type (type of first argument of erase) will overflow (wrap around) to value 18446744073709551615 which is defnitely out of bounds, and out of memory border, hence your program may crash and/or hang. Also erase crashes when there is too many chars deleted, i.e. for erase s.erase(a, b) you have to watch that a + b <= s.size(), it is not controlled by erase function.
See documentation of erase method, and don't put negative values as arguments to this method. Check that your algorithm never has negative value i.e. never i < k when calling s.erase(i-k, k);, also never i-k + k > s.size(). To make sure there is no program crash you may do following:
int start = std::min(std::max(0, i-k), int(s.size()));
int num = std::min(k, std::max(0, int(s.size()) - start));
s.erase(start, num);

Why does my for loop throw an "out_of_range" error?

I am learning c++ and for a test problem I am using a for loop with condition prices.size()-1 so the vector does not go out of range.
std::vector<int> prices {7,1,5,3,6,4};
int maxProfit(vector<int>& prices) {
int total {0};
for (size_t i = 0; i < prices.size()-1; i++) {
if (prices.at(i+1) > prices.at(i)) {
total += prices.at(i+1) - prices.at(i);
}
}
return total;
}
But it is throwing this this runtime error that I cannot decipher:
terminate called after throwing an instance of 'std::out_of_range' what(): vector::_M_range_check: __n (which is 1) >= this->size() (which is 0)
I cannot figure out the problem, can someone please show me what I am doing wrong.
Look at the error message carefully:
this->size() (which is 0)
The error message indicates that the passed-in vector is empty. Its size() is 0. Now take a closer look at the for-loop:
for (size_t i = 0; i < prices.size()-1; i++)
We've established that prices.size() is 0, so this becomes, effectively:
for (size_t i = 0; i < -1; i++)
But i is a size_t, which is an unsigned type, so -1 gets casted to an unsigned type.
Now, perform a little experiment yourself, see what output you get from the following statement:
std::cout << (size_t)-1 << std::endl;
Because of this, even though the vector is empty, the for loop's condition will still evaluate to true, and inside the for loop the code will attempt to access a non-existent array value, hence the exception.
Note that the function's parameter of prices has nothing to do with the global prices vector. The code from your program that you did not show passes in an empty vector, resulting in this error. Why the vector that gets passed in is empty, this is something you will need to figure out on your own.
Note that it's fairly easy to tweak the for-loop, just slightly, so that this edge case gets correctly handled. Simply change the for loop's condition as follows:
for (size_t i = 0; i+1 < prices.size(); i++)
Even though this seems to be the same thing, it's not (at least until you manage to create an array with about four billion, or so, values -- more on a 64 bit platform). Welcome to C++.

Program receives `SIGTRAP` when deallocating vector

I have this code which is supposed to look for elements present in all vectors in a std::vector<std::vector<int>>:
for(int x = 0;x < list.size();x++){
for(int y = 0;y < list[x].size();y++){
std::vector<std::vector<int>::iterator> ptr;
for(int z = 1;z < list.size();z++){
std::vector<int>::iterator iter = std::find(list[z].begin(),
list[z].end(), list[x][y]);
if(iter != list[z].end()){
ptr.push_back(iter);
}else
goto fail;
}
list[0].erase(list[0].begin() + y);
for(int z = 1;z <= ptr.size();z++){
list[z].erase(ptr[z - 1]);
}
fail: continue;
}
}
The program always produces wrong output and randomly crashes. Debugging shows that it receives SIGTRAP when deconstructing list in ntdll. This happens randomly, but the program never works correctly. I don't have any breakpoints in the code.
These are the errors I found in the code some time after asking this question:
The code for determining which iterator is from which array was designed only for list[0], instead of being designed for list[x], causing erase() being called with iterators belonging to another vector, causing memory corruption.
x was replaced with 0 in some places (forgot to change it).
list was being corrupted by other code in the program (fixed now).
These are the fixes:
Used an iterator to std::vector<std::vector<int>::iterator> and if(z==x)continue;else{list[z].erase(*iter); iter++;} to make sure iter always points to the correct element.
Replaced 0 with x.
Fixed problems in other places in the program.
The program works correctly now, thanks for trying to help me.

Fibonacci Sequence with vectors

I'm currently trying to solve some problems of the Euler-Projects, but I'm currently stuck at the second problem. Here is what I have right now:
void p002()
{
unsigned int result = 0;
std::vector<int> fibonacci{ 1,2 };
for (int i = 2; fibonacci.at(i) < 4000000; i++)
{
fibonacci.at(i) = fibonacci.at(i - 1) + fibonacci.at(i - 2); //<- Doesn't work
if (fibonacci.at(i) % 2 == 0)
result += fibonacci.at(i);
}
std::cout << result;
}
Could someone help me out and tell me why this one line doesn't seem to work? (I get an "abort() called" error when trying to execute the code.)
In case anyone wonders: The task is to get the sum of all integers of the fibonacci sequence with a lower value than 4,000,000 which are even-valued.
Thanks!
vector::at throws an exception if you try to access an element at an index that is out of bounds. Your vector contains 2 elements (at indices 0 and 1). Therefore fibonacci.at(2) is out of bounds, and an exception is thrown. You don't catch the exception, so std::terminate is called. By default, std::terminate points to abort which terminates your process.
Solution: Add enough elements into the vector so that fibonacci.at(i) isn't out of bounds.

"Expression: list iterators incompatible" happening randomly during iteration through a list

I have been trying to use std::list, however my work has been sabotaged by following error:
Debug Assertion Failed!
Program: C:\Windows\system32\MSVCP120D.dll
File: c:\program files (x86)\microsoft visual studio 12.0\vc\include\list
Line: 289
Expression: list iterators incompatible
For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.
(Press Retry to debug the application)
I have searched a little (a few hours in fact), yet nothing has solved my problem.
Error shows itself in following function:
void Plane::createFrame(){
for( int i = 0; i < 400; i++ ){
frame[i] = '_';
}
for (std::list<Unit>::iterator iterator = units_container.begin();
iterator != units_container.end(); ++iterator) {
iterator->draw(frame, 20);
}
}
Where draw function looks like this:
void Unit::draw( char(&world)[400], int width ){
world[ position ] = avatar;
}
Another interesting thing is thing is that I managed to "contain" this error:
void Plane::createFrame(){
for( int i = 0; i < 400; i++ ){
frame[i] = '_';
}
for (std::list<Unit>::iterator iterator = units_container.begin();
iterator != units_container.end(); ++iterator) {
if( iterator->getPosition() < 0 ||
iterator->getPosition() > 399 ){
break;
}
iterator->draw(frame, 20);
}
}
Changed createFrame() seems immune to previous error.
If I change my code same error my occur in different places (change is necessary, though. Right now it is always createFrame() that shows error). It always show within almost the same for maybe with different function being invoked.
createFrame() is being invoked in a loop. Error usually happens after 100 lap. Changed createFrame() uses break; randomly, however error never shows.
There are no other threads that could access list.
I'm using erase() but error doesn't seem connected in any way.
I hope I didn't miss anything obvious, but now I can't really be sure.
Thanks for your time.
You have an array which is passed to Unit::draw as char(&world)[400], and you are writing into index position of that array.
If position is not between 0 and 399, this will result in undefined behavior. This can cause various symptoms: your code may crash, it may work incorrectly, or it may display seemingly unrelated error messages such as the one you are getting about iterators.
When you added the check that position is between 0 and 399, the error stopped happening here. You say that it now happens elsewhere, so you should check if there is any out-of-bounds array access there (or any other kind of undefined behavior). It may be best to ensure that position doesn't get assigned an invalid value in the first place.