Adding pairs to a vector C++ - c++

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.

Related

What is the return value of the given function on encountering an exception?

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: "

std::vector segfaulting instead of throwing exception

I am attempting to create a container class for a std::vector, to teach myself a bit more about templates, overloading operators, and managing exceptions.
For the moment, I'm just defining the basic operations. I have a template class listed below; I've overloaded the += and [] operators to push_back the vector with a T and access the elements of the vector directly, respectively. This works as expected.
The += operator does what it's supposed to do, and attempting to use the [] operator on an element out of range will throw the exception as intended.
Here is the prototype class and implementation as it currently stands:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
template <class T>
class Inventory
{
public:
void operator += (const T& b) { backpack.push_back(b); }
T operator [] (const unsigned& b)
{
if (backpack.empty() || backpack.size() < b)
throw string("Out of Range");
return backpack[b];
}
void operator -= (const unsigned& b)
{
if (backpack.empty() || backpack.size() < b)
throw string("No such element exists.");
backpack.erase(backpack.begin() + b);
}
private:
vector<int> backpack;
};
int main()
{
Inventory<int> pack;
pack += 2;
pack += 4;
try
{
cout << "It was " << pack[0] << endl;
cout << "It was " << pack[1] << endl;
pack -= 0;
cout << "It is now " << pack[0] << endl;
//pack -= 1; // Segfaults?
}
catch (string e)
{
cout << "Error: " << e << endl;
}
}
The issue is with the -= operator, intended to erase an element at the indicated position on the right hand side. When I stay within the boundaries of the vector, this works as intended; however, I do not get an exception if I specify an out of bounds number to erase; I get a seg-fault instead. I have attempted to determine the exact point the segfault occurs by adding additional print commands:
void operator -= (const unsigned& b)
{
cout << "In Overload!\n";
if (backpack.empty() || backpack.size() < b)
{
cout << "Exception!\n";
throw string("No such element exists.");
}
backpack.erase(backpack.begin() + b);
}
The "Exception!" line is never reached. The program faults before it can reach that point, even though I should be evaluating for undefined behavior. I believe I'm missing a key component in understanding how this process works. Is there a way I should be writing this so it can throw instead of fault?
Compiling using g++ -std=c++17 -Wall -Wextra -pedantic on Linux x64 architecture.
Your error checking is off by 1.
if (backpack.empty() || backpack.size() < b)
If the std::vector backpack contains only two values, backpack.size() is going to be 2, and backpack will contain backpack[0] and backpack[1].
Unfortunately, if the index b gets passed in as 2, this code will still attempt to access backpack[2], resulting in undefined behavior.
In fact, the entire if statement can be simply rewritten as:
if (b >= backpack.size())
throw string("Out of Range");
You have an "off by one" error in your code.,
Consider what happens if the array is not empty and b == backpack.size() in the code.
if (backpack.empty() || backpack.size() < b)
throw string("Out of Range");
return backpack[b];
In this case, valid indices for elements of backpack are 0 through to backpack.size() - 1.
If b == backpack.size(), the code will NOT throw an exception, and WILL attempt to return backpack[backpack.size()] which gives undefined behaviour.
One possible symptom of undefined behaviour is a "segfault".
One way to avoid the problem is to change the test to backpack.size() <= b.
Another alternative is to take advantage of std::vector::at() which will throw a std::out_of_range exception on an out-of-bounds index:
T operator [] (const unsigned& b)
{
try
{
return backpack.at(b);
}
catch (std::out_of_range& e)
{
throw string("Out of Range");
}
}
void operator -= (const unsigned& b)
{
try
{
backpack.at(b);
backpack.erase(backpack.begin() + b);
}
catch(std::out_of_range& e)
{
throw std::string("No such element exists.");
}
}
Live Example

sometimes getting a segmentation fault (core dumped)

my program will sometimes run okay but sometimes it crashes in the middle of running with a segmentation fault. and the fault will come at different times each time i run the program. i debugged with gdb and found that the problem is in this function
int chooseLink(int &h, vector<Edge> &link) {
double r = 1.0*rand() / RAND_MAX;
if (link[link[h].l_ID].q == link[link[h].r_ID].q) { // this is where the error occurs
if (r<0.5)
return link[h].l_ID;
return link[h].r_ID;
}
else {
if (r < link[link[h].l_ID].q / (link[link[h].l_ID].q + link[link[h].r_ID].q))
return link[h].l_ID;
return link[h].r_ID;
}
}
my program involves calling this function millions of times. can anyone suggest what the problem may be? I'm pretty sure the vector 'link' is not going beyond its capacity. this is my first time posting a problem, so sorry if I haven't provided enough information
update
someone asked why i'm passing h by reference. i thought that passing by reference is better than passing by value because it saves space and the program will run faster. is that not correct?
someone asked for the edge class, so here it is
class Edge {
public:
int ID; // ID of edge
bool type; // true for constant, false for variable
double q; // quantity on the edge
int l_ID = 0; // ID of left edge (equals 0 if doesn't exist)
int r_ID = 0; // ID of right edge
void assignType(double &p) {
if (p == 0.5)
type = false;
else
type = true;
}
};
i added a try-catch block to the function so it looks like this:
int chooseLink(int &h, vector<Edge> &link) {
try {
if (h<0 || h>=link.size() ) {
throw h;
}
} catch(...) {
cout << "ERROR: h = " << h << endl;
}
double r = 1.0*rand() / RAND_MAX;
if (link[link[h].l_ID].q == link[link[h].r_ID].q) { // this is where the error occurs
if (r<0.5)
return link[h].l_ID;
return link[h].r_ID;
}
else {
if (r < link[link[h].l_ID].q / (link[link[h].l_ID].q + link[link[h].r_ID].q))
return link[h].l_ID;
return link[h].r_ID;
}
}
and now i don't get the segmentation fault at all. Also, the program runs fine without ever throwing an exception. what's going on? when i remove this try-catch block, i get the segfault again. i don't understand it
The first suggestion is always to boundary or range check your parameters:
int chooseLink(int h, vector<Edge> &link)
{
const unsigned int container_size = link.size();
// Check index for range.
if ((h < 0) || (h >= container.size)
{
// Report error here.
}
else
{
// More checking.
const int left_id = link[h].l_ID;
const int right_id = link[h].r_ID;
if ((left_id < 0) || (left_id >= container.size))
{
// Perform error handling
}
if ((right_id < 0) || (right_id >= container_size))
{
// Perform error handling
}
// remember to use 'const' for items that won't change.
const double r = 1.0*rand() / RAND_MAX;
if (link[left_id].q == link[right_id].q)
{
// ALWAYS use braces, even for single statements.
if (r<0.5)
{
return left_id;
}
return right_id;
}
else
{
if (r < link[left_id].q / (link[left_id].q + link[right_id].q))
{
return left_id;
}
return right_id;
}
// What does it return here?
}
}
When in doubt, range check your variables.
Also, check your logic so that all paths of execution return a value.

Searching a vector of object pointers

I have a Player class where each object of the type Class has a name, wins, losses, and draws. Each object of the Player class is created by calling the_player = new Player(the_name). When the user inputs a new name to add a Player object to the program a pointer is pushed into a vector AllPlayers. The program should check before pushing the new pointer that the desired player does not already exist in said vector. I have to do this check several times throughout my program so I thought I'd write a function for it. Here is my function:
int findPlayer(vector<Player*> &vals, string name_in)
{
for (int i = 0; i < vals.size(); i++){
if (vals[i]->getName() == name_in){
cout << vals[i]->toString() << endl;
return i;
}
else
return -1;
}
};
When the option is requested to add a new Player the following code is used:
do {
cout << "Name: ";
cin >> the_name;
if (findPlayer(AllPlayers, the_name) != -1){
cerr << "Player already exists\n";
}
} while (findPlayer(AllPlayers, the_name) != -1);
the_player = new Player(the_name);
AllPlayers.push_back(the_player);
For some reason, though, every time I try to add a new player it throws "Player already exists" and never leaves the do-while loop. This is even true when the AllPlayers vector is empty. I added a cout << findPlayer(AllPlayers, the_name) for debugging and it printed 4192252 which I assume is the largest element possible in a vector.
So the question is: Why does it return 4192252 rather than -1?
If vals is empty then the for loop is never entered and the function exits without hitting a return statement. Meaning that you get a random value returned instead, in this case 4192252 happens to be in the return register. Your compiler warnings will have told you this if you read them.
What you think, what will be returned from findPlayer if vals is empty?
Is it defined?
If the vector is empty, you don't enter the loop at all, so don't reach a return statement and don't return a valid value. You should enable compiler warnings to catch this error.
Otherwise, you only check the first item, and return immediately whether or not it matched. You want to return if you find a match, but keep looking otherwise, and only return -1 if there is no match:
for (int i = 0; i < vals.size(); i++){
if (vals[i]->getName() == name_in){
cout << vals[i]->toString() << endl;
return i;
}
}
return -1;
The find player function should be something like:
int findPlayer(vector<Player*> &vals, string name_in)
{
if(vals.size() == 0)
return -1;
for (int i = 0; i < vals.size(); i++){
if (vals[i]->getName() == name_in){
cout << vals[i]->toString() << endl;
return i;
}
}
return -1;
};
Rewrite the function the following way
bool findPlayer( const std::vector<Player*> &vals, const std::string &name_in )
{
std::vector<Player*>::size_tyoe i = 0;
while ( i < vals.size() && vals[i]->getName() != name_in ) ++i;
return i != vals.size();
}
Take into account that member function getName has to be defined with qualifier const.
As for your function then it returns nothing in case when the vector is empty or returns -1 in case when the first element of the vector does not coincide with the string.
Take into account that there is standard algorithm std::find_if declared in header <algorithm> that can be used instead of your function.

C++: Catch block not catching?

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