I've got a specific Exception class I'm wanting to throw from a class method and catch from it's calling code in the main() function.
However when I run it, I get the following error:
Unhandled exception at 0x775915ee in OpenHashTable.exe: 0xC0000005: Access violation. as if it isn't being handled. I can't see why this is happeing. Here's the involved code:
main() {
......
case 'i':
{
cout << "Enter the positive integer you wish to insert: ";
//Input Validation.
if (!(cin >> number))
{
cout << "Please enter a valid positive integer...\n\n";
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n'); //Taken from http://stackoverflow.com/questions/2075898/good-input-validation-loop-using-cin-c
break;
}
try
{
hashTable.add(abs(number)); //Add positive only integer
}
catch (FullTableException& fte)
{
cout << "HashTable is full!" << endl;
break;
}
catch (DuplicateElementException& dee) //NOT BEING CAUGHT?
{
cout << "HashTable already contains that element." << endl;
break;
}
cout << abs(number) << " added!\n\n";
break;
}
.......
}
Here's the exception being thrown in the HashTable::add() method
//Adds an element into the appropriate index
bool OpenHashTable::add(int toAdd) throw(FullTableException, DuplicateElementException)
{
int index = hash(toAdd);
//Check for duplicate
if (search(toAdd))
throw DuplicateElementException(); //NOT ACTUALLY THROWING??
if (arr[index] != 0) //If element is occupied //GET AN ACCESS VIOLATION HERE
{
int j = 0;
//Linear Probing...
for ( unsigned int i = index + 1; j < 100; i = ((i+1) % 100) )
{
if (arr[i] != 0 && arr[i] != -1) //If element is occupied
{
j++; //Keep count of how many tries, for full array
continue;
}
else
{
arr[i] = toAdd; //Add to array
size++; //Increment size
break;
}
}
if (j == 100) //We've checked all possible elements
throw FullTableException(); //No spaces
}
else
{
arr[index] = toAdd; //Add to array straight away
size++; //Increment size
}
return true; //Successfully added
}
EDIT: search() method:
bool OpenHashTable::search(int toSearch)
{
int index = hash(toSearch);
if (arr[index] == toSearch)
return true; //Found at index
else
{
int j = 0;
//Linear search for value
for ( unsigned int i = index + 1; j < 100; i = ((i+1) % 100) )
{
if (arr[i] == toSearch)
return true; //found
else if (arr[i] == 0)
return false; //Not in HashTable
else
continue; //Probe next element
}
if (j == 100)
return false; //Not in HashTable
}
return true;
}
EDIT: _try..._except() Call Stack:
ntdll.dll!775915ee()
[Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll]
ntdll.dll!775915ee()
ntdll.dll!7761852f()
ntdll.dll!776372ec()
ntdll.dll!7760063e()
ntdll.dll!775fabf9()
ntdll.dll!77580143()
KernelBase.dll!75c5b9bc()
KernelBase.dll!75c5b9bc()
KernelBase.dll!75c5b9bc()
msvcr100d.dll!_CxxThrowException(void * pExceptionObject, const _s__ThrowInfo * pThrowInfo) Line 157 C++
OpenHashTable.exe!OpenHashTable::add(int toAdd) Line 100 //THIS IS "throw DuplicateElementException()"
OpenHashTable.exe!main() Line 267 //THIS IS "hashTable.add(abs(number));"
EDIT: DuplicateElementException:
//Just an empty class
class DuplicateElementException : public exception
{
private:
public:
DuplicateElementException(); //Constructor
~DuplicateElementException(); //Destructor
};
//empty constructor and destructor definitions...
Any help is much appreciated.
Thanks
Calum
The exception thrown is a SEH exception "Access violation", which means that you read or write from an invalid address. It's probably a bug in search or hash. and your program doesn't get to the line where you throw DuplicateElementException.
Besides, exception specification (the throw after the function prototype) are deprecated, so don't use them.
The Access violation exception being thrown is an SEH exception and will not be caught by a C++ catch block. You're most likely writing beyond the bounds of some array, which is causing the exception to be thrown.
To debug the problem, surround everything within the code inside main in a __try block and place breakpoints within the accompanying __except block. Details of how to do this can be found in the MSDN docs. You can use the code in there almost verbatim. Run your program in Debug mode and when the breakpoint is hit inspect the call stack to figure out what line the SEH exception is being thrown at.
Also, unless you have a very compelling reason to be using a C array, you should be using an std::array (if the size of the array is fixed) or an std::vector for the hash table. On Visual Studio operator[] for both of these will perform range checks in Debug mode and throw an std::out_of_range exception if your index is out of bounds. You can also use the at() member function with both to have them perform bounds checking in Release mode also. In either case, it is a lot easier to debug than having to mess with the SEH stuff.
EDIT:
A little bit of code refactoring will be required to debug the problem using __try - __except because you cannot surround code containing C++ object destruction with __try.
To get around this, create a function called int mainHelper() and move all the code from within main to this function. Now, your code should look like this:
int mainHelper()
{
/* All your code from main goes here */
}
int main()
{
__try {
return mainHelper();
} __except( filter(GetExceptionCode(), GetExceptionInformation()) ) {
puts("in except");
}
}
It seems like index is out of bound of the array arr. It makes your process read from memory that isn't allocated to it and crash. This is not a C++ exception but something the OS tells your program.
There is a very easy way to catch any kind of exception (division by zero, access violation, etc.) in Visual Studio using try -> catch (...) block. A minor project tweaking is enough. Just enable /EHa option in project settings. See Project Properties -> C/C++ -> Code Generation -> Modify the Enable C++ Exceptions to "Yes With SEH Exceptions". That's it!
See details here:
http://msdn.microsoft.com/en-us/library/1deeycx5(v=vs.80).aspx
Related
I am trying to figure out a way for qsort to throw an exception or indicate an error condition if the compare function finds that the elements are, for some reason, invalid for sorting.
For example, in this compare function, I need to indicate an error condition that my sorting is invalid if the return value of some_function is 5.
How should I modify my compare function?
int compare (const void * a, const void * b)
{
int ret1 = some_func(a);
int ret2 = some_func(b):
return ( ret1 - ret2 );
}
I am dealing with a legacy code base so I'm not in the position to use std::sort and due to the nature of the implementation calling some_func before hand might also involve huge amount of changes so I'm looking to understand if a workaround is possible.
C++ allows you to throw whatever you need, not only exceptions but also other types, you could do something like throw an int if it suits your purposes and catch where you call the function with a try-catch block.
For what you need I think you can use STL exception library:
Demostrative example:
#include <iostream>
#include <exception>
int count = 0;
int compare(const void *a, const void *b)
{
int ret1 = *(int*)a > *(int*)b;
if (++count == 5) //throws exception when count reaches 5
throw std::invalid_argument("Argument is not sortable");
//you could throw count by simply using throw count
return ret1;
}
int main()
{
int x[]{2,1,3,5,6,1,7,2,5,3};
try
{
//will sort until exception is thrown
qsort(x, sizeof x / sizeof *x, sizeof(int), compare);
}
catch (const std::exception& e)
{
std::cout << e.what() << std::endl; //print exception in the console
//handle the exception here
//if you were to throw count you could cach it with
//catch (int &e)
}
//note that the values were sorted until the exception was thrown
for (int i = 0; i < sizeof x / sizeof *x; i++){
std::cout << x[i] << " ";
}
}
Output:
Argument is not sortable
1 2 3 5 6 1 7 2 5 3
^
sorting
stopped
here
Throwing an exception is potentially expensive, so you probably want to return an error condition. However, doing either approach inside the compare function is needlessly expensive in this case, since you would be doing the check multiple times for every element. Instead, you could just check for the error condition before calling qsort which is much more efficient:
auto ok = std::none_of(/* range */, /* predicate */);
if (ok)
std::qsort(/* ... */)
else
// report error
this simple loop method is unable to run and an error arises "app crashed". when i checked this in an online compiler it gave 'segmentation fault(core dumped)'-
string studies(setMatter ch) {
string a = "LISTEN CAREFULLY!\n";
int i = 0;
while (i <= ch.a.quantity()) {
a += ch.a.getAns(i);
i++;
}
return a;
}
also see for reference of methods in the above code-
class Answer {
private:
vector<string> ch;
public:
void setAns(string ans) { ch.push_back(ans); }
string getAns(int num) { return (ch[num]); }
int quantity() { return ch.size(); }
};
am i accessing elements out of bond? but i dont know where as i every number starts from 0 in programming
Yes you are.
while(i<=ch.a.quantity()){
should be
while(i<ch.a.quantity()){
Valid vector indexes are zero up to the size of the vector minus one. That should be obvious, if the valid indexes started at zero and went to the size of the vector then there would be one more valid index than the size of the vector, which makes no sense.
Generally you use a for loop for this kind of task
for (int i = 0; i < ch.a.quantity(); i++) {
a += ch.a.getAns(i);
}
It's a little easier to read that way.
First of all sorry for too much code
Here there is a vector (teamNum) with type class, the class contain a vector (player) with type struct, it is a little complicated, but here in this function I need to check if there is a player in teamNum which contain tName equal to _tname (function parameter) contain (the player) pID equal to _pID (function parameter)
bool thereIsSimilarID(string _tname, int _pID)
{
for (int i = 0; i < teamNum.size(); i++)
{
if (teamNum[i].tName == _tname)
{
for (int j = 0; j < teamNum[i].player.size(); j++)
{
if (teamNum[i].player[j].pID == _pID)
return true;
}
}
else if (i == (teamNum.size() - 1))
{
return false;
}
}
}
And in the main
int main()
{
cout << "\n" << thereIsSimilarID("Leverpool", 1) << endl;
}
The output is 24 !!!!!
(good note that this happen just when the team (Leverpool) is the last team in the vector teamNum)
Again sorry for too much code but I need to know the bug not only fix the problem I need to learn from you
You encountered undefined behaviour.
If you take the if (teamNum[i].tName == _tname)-branch on the last element, but find no player with the correct pID, you don't return anything. Which means, that the return value is whatever random value is currently in the memory location that should hold the return value. In your case it happens to 24. But theoretically, everything could happen.
The same problem occurs when teamNum is empty.
The solution is to make sure to always return a value from a function (except if it has return type void of course):
bool thereIsSimilarID(string _tname, int _pID)
{
for (int i = 0; i < teamNum.size(); i++)
{
// In this loop return true if you find a matching element
}
// If no matching element was found we reach this point and make sure to return a value
return false;
}
You should take a look at your compiler settings and enable all the warnings. And often it's good to let it treat certain warnings as errors.
So, I'm attempting to add pairs to a vector, but they must successfully pass 2 criteria:
Their weight or 2nd value is greater than or equal to zero. and throws a string error if it does.
The vector must not already contain the key or the first value
It specifically must be done while the function returns a void type, however for some reason, this logic doesn't seem to be working. Any suggestions?
void add(KEY_T key, WEIGHT_T weight)
{
bool contains = false;
if (weight < 0)
{
std::cout << "ERROR, invalid weight" << std::endl; //Throw error.
}
for (int x = 0; x < _valueToWeightMap.size(); x++)
{
if (_valueToWeightMap[x].first == key)
{
contains = true;
}
}
if (weight > 0 && contains == false)
{
_valueToWeightMap.push_back(std::make_pair(key, weight));
}
}
Here is the main:
int main()
{
DiscreteDistribution<std::string> dist1;
dist1.add("Helmet", -1);
dist1.add("Gloves", 5);
dist1.add("Gloves", 5);
dist1.add("cloud", 8);
For some reason, I'm not getting an error when I try to add Helmet as -1. Any suggestions?
This line:
std::cout << "ERROR, invalid weight" << std::endl; //Throw error.
does not do what the comment says (throw an error). This line:
throw "ERROR, invalid weight"; //Throw error.
does. However, I strongly recommend that you only ever throw exceptions derived from std::exception. This:
throw std::range_error("ERROR, invalid weight"); //Throw error.
is much better.
checkUsername() checks the username's length, and returns true when length is greater than or equal to 5. Otherwise it returns false.
The function checkUsername() should return false on BadLengthException(), but it doesn't seem to appear as none of the code within checkUsername() and BadLengthException::what() returns false. But still the program is working fine when it encounters a username of length less than 5. What's going on here? How is the return value passed false?
class BadLengthException: public exception{
public:
int n;
BadLengthException(int x) { n=x; };
virtual int what() throw() {
return n;
}
};
/*
This function checks the username's length,
and returns true when length is greater than or equal to 5.
Otherwise it returns false.
*/
bool checkUsername(string username) {
bool isValid = true;
int n = username.length();
if(n < 5) {
throw BadLengthException(n); //the problem
}
for(int i = 0; i < n-1; i++) {
if(username[i] == 'w' && username[i+1] == 'w') {
isValid = false;
}
}
return isValid;
}
int main() {
int T; cin >> T;
while(T--) {
string username;
cin >> username;
try {
bool isValid = checkUsername(username);
if(isValid) {
cout << "Valid" << '\n';
} else {
cout << "Invalid" << '\n';
}
} catch (BadLengthException e) {
cout << "Too short: " << e.what() << '\n';
}
}
return 0;
}
A function can either return a value or throw an exception, it can't do both, they're mutually exclusive. If it successfully returns a value that means the code didn't throw an exception, and if an exception was thrown then it means it didn't make it to the point of returning a value.
Further to that, capturing the return value is also interrupted, the code jumps right to the catch block you've defined. It's like a hard goto in concept, if you ignore things like automatic object destruction and finally type implementations which will happen in the process of an exception bubbling up.
When the exception is thrown in checkUsername(), it stops processing in that function and returns to the calling function which is main(). Because the call was made in a try block the exception is handled by the catch block.
The if() statement is completely ignored and the catch doesn't care about what happened in that function and just prints "Too short: "