Reputation: 1192
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
Upvotes: 0
Views: 1958
Reputation: 1303
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
Upvotes: -2
Reputation: 109289
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");
}
}
Upvotes: 4
Reputation: 3934
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.
Upvotes: 0
Reputation: 72539
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.
Upvotes: 5