Having a tough time understanding exception handling c++ [closed] - c++

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 7 years ago.
Improve this question
I am having a very tough time understanding exception handling after watching online tutorials and reading up on it. I am trying to pass test driven development, and I can't. What I have come up with so far is this. I am supposed to use this struct
struct ArrayException
{
ArrayException(string newMessage = "error") :message(newMessage)
{
}
string message;
};
The first try.
int sum(int* theArray, unsigned int arraySize)
{
try
{
if (theArray = NULL)
{
throw ArrayException("NULL ARRAY REFERENCE");
}
}
catch (int* param)
{
cout << "you can't have " << param << " as an array size";
}
int sum = 0;
for (int i = 1; i < arraySize; i++)
{
sum += theArray[i];
}
return sum;
}
I also tried doing it this way.
int sum(int* theArray, unsigned int arraySize)
{
if (theArray = NULL)
{
throw ArrayException("NULL ARRAY REFERENCE");
}
else
{
int sum = 0;
for (int i = 1; i < arraySize; i++)
{
sum += theArray[i];
}
return sum;
}
}

While the post does not specifically mention it, I take it that the question is why exception is not caught? The answer is simple - because exception thrown is of type ArrayException, and catch is done with the type int*.

The best way to get a grip on this stuff is as πάντα ῥεῖ recommended: get a good book. Here's a good place to start selecting books: The Definitive C++ Book Guide and List
The rest is a code block with comments where I figured they were needed.
#include <iostream>
// removed the using namespace std;
struct ArrayException
{
ArrayException(std::string newMessage = "error") :
message(newMessage)
{
}
std::string message;
};
int sum(int* theArray, size_t arraySize) // change made here:
// size_t better suited than unsigned int for indexes
{
//throw std::out_of_range("BOOM!"); //uncomment to trigger a std::exception
//throw 42; // uncomment to trigger the unknown exception
if (theArray == NULL)
{
throw ArrayException("NULL ARRAY REFERENCE"); //perfect!
}
else
{
int sum = 0;
for (size_t i = 0; i < arraySize; i++) // changes made here:
// size_t not int to get rid of signed/unsigned conflict
// starting with array index 0, not 1
{
sum += theArray[i];
}
return sum;
}
}
int main()
{
try
{
sum (NULL, 10); // NULL address to force the exception
}
catch (ArrayException & param) // catch the custom exception
// catch by reference where possible
{
std::cout << "This bad stuff happened: " << param.message << std::endl;
}
// extra stuff to show what can also be done
catch (std::exception & stdexcpt) // catch any standard exceptions and
// print their message
{
std::cout << "Standard exception thrown: " << stdexcpt.what() << std::endl;
}
catch (...) // catch anything else that was thrown and doesn't
// correspond to any expectation
{
std::cout << "No idea what happened." << std::endl;
}
}

Related

in c++ i get the error: cannot convert 'bool' to 'bool*' in return [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
Im new to c++ and im trying to get a bool* function with a dynamic array as its parameter and its size to return true or false when none of them is zero but im getting an error: cannot convert 'bool' to 'bool*' in return.
bool* noneZero(int *zero, int N) {
int PL = 0;
for (int i = 0; i < N; i++) {
if (i == 0) {
PL++;
}
}
if (PL == N)
return false; //cannot convert 'bool' to 'bool*' in return
else
return true; //cannot convert 'bool' to 'bool*' in return
}
int main(int argc, char** argv) {
int *z=new int[5]{0,0,0,0,0};
cout << noneZero(z,5);
}
Also the question is how the teacher gave it to me. we dont work with vectors. Basically i have to return false when all of the numbers in my dynamic array are 0 and true when they arent. My question is why i get an error: cannot convert 'bool' to 'bool*' in return
Frankly, there are many problems in your code and I suggest to start from scratch.
First, dynamic arrays in C++ are std::vector. You need a good reason to use something else.
Next, your function is too complicated. You need not count the number of zeros if all you want is to check if there is none or at least one:
bool noneZero(const std::vector<int>& in) {
for (size_t i=0; i< in.size(); ++i) { // a vector "knows" its size !
if ( in[i] == 0 ) return false; // no need to search further
}
return true;
}
int main() {
std::vector<int> z{1,2,3,4,5};
bool x = noneZero(z);
if (x) std::cout << "there is no 0 in the vector\n";
for (const auto& e : z) {
std::cout << e << " ";
}
}
A std::vector manages the memory for you, ie no need for manual new or delete. It is not clear why you use the pointer returned from the function as if it points to an array (it does not and your code has undefined behavior). I added a loop that prints the vectors elements.
Problem:
A bool* must return a pointer a pointer to a bool, not a bool itself.
You're checking the value of i, not the values of the array.
Solution:
Change the function from a bool* to a bool.
Change i == 0 to *(zero + i) == 0.
Additional information:
Seems like you're using using namespace std;. using namespace std; is considered a bad practice (More info here).
You probably should use std::vector if you can.
Full code:
#include <iostream>
bool noneZero(int *zero, int N) {
int PL = 0;
for (int i = 0; i < N; i++) {
if (*(zero + i) == 0) {
PL++;
}
}
if (PL == N)
return false;
else
return true;
}
int main(int argc, char** argv) {
int *z = new int[5]{0,0,0,0,0};
std::cout << noneZero(z,5);
delete[] z;
}

C++ catch error and exit the function

I use try{} catch(){} to handle errors in a function which return a template type.
T get (int iOffset) const
{
try {
checkIndex(iOffset);
}
catch (char const* msg) {
std::cout << msg << std::endl;
}
int index = (m_iReadIdx + iOffset) % m_iBuffLength;
float a = m_ptBuff[index];
return a;
}
The function would first call checkIndex to check whether the input is out of range and throw an error if so.
However, I don't want the outside get return any value if checkIndex throws an error, because the returned value may be used by other functions or printed out incorrectly. If I put a return in the catch block, I don't know what to return since it's a template. If I don't, the codes following the catch block will still get executed and therefore return a value.
Is there any way to do that? I'm new to C++ and wondering how people usually do the error handling in this condition? THanks!
However, I don't want the outside get return any value if checkIndex throws an error, because the returned value may be used by other functions or printed out incorrectly.
You can always re-throw the exception after logging
T get (int iOffset) const
{
try {
checkIndex(iOffset);
}
catch (char const* msg) {
std::cout << msg << std::endl;
throw; // Just re-throw the exception
}
int index = (m_iReadIdx + iOffset) % m_iBuffLength;
float a = m_ptBuff[index];
return a;
}
You can also use optional for this situation. One of idea of this construct was to indicate that value cannot be set correctly because of some mistakes.
std::optional< T > get (int iOffset ) const
{
try {
checkIndex(iOffset);
}
catch (char const* msg) {
std::cout << msg << std::endl;
return std::optional< T >();
}
int index = (m_iReadIdx + iOffset) % m_iBuffLength;
float a = m_ptBuff[index];
return return std::optional< T >( a );
}
Using of such function can look like this:
auto result = get( someOffset );
if( result )
{
// correct, processing result
}
One of the easiest way is first to decide: What exactly should your get() return if it cannot return the 'proper' value?
In many cases it is just 0, or -1, or some other special value.
And then the code become very simple:
T get (int iOffset) const
{
T a;
try {
checkIndex(iOffset);
int index = (m_iReadIdx + iOffset) % m_iBuffLength;
a = m_ptBuff[index];
}
catch (char const* msg) {
a = special_value_for_errors;
std::cout << msg << std::endl;
}
return a;
}

C++ struct behavior

I'm trying to improve my knowledge of the C++ language and am making a stack of stacks. Below is a very short example of my question: why do I have to directly access the members of the struct in order to change them instead of using functions to do that? If anyone knows why this happens a answer is very appreciated! Thanks
#include <iostream>
#include <vector>
using namespace std;
struct Stack {
int N;
vector<int> stack;
int len() { return stack.size(); }
void add(int N) { stack.push_back(N); }
};
struct Stacks {
vector<Stack> stacks;
Stack getStackAtIndex(int i) { return stacks[i]; }
void addStack(Stack stack) { stacks.push_back(stack); }
void printStacks() {
cout << "Printing stacks" << endl;
for (int i = 0; i < stacks.size(); i++) {
cout << "Stack #" << i << ": ";
for (int j = 0; j < stacks[i].len(); j++) {
cout << stacks[i].stack[j];
if (j != stacks[i].len()-1) cout << " -> ";
}
cout << endl;
}
}
};
int main() {
Stacks stacks;
Stack stack;
stack.add(1);
stacks.addStack(stack);
// This does not work:
// stacks.getStackAtIndex(0).add(2);
// This works:
stacks.stacks[0].stack.push_back(2);
stacks.printStacks();
return 0;
}
stacks.getStackAtIndex(0)
returns a copy of the first Stack, while
stacks.stacks[0]
returns a reference to it. (c.f. std::vector::operator[]).
You can fix this by changing the return type of getStackAtIndex to a reference of Stack:
Stack& getStackAtIndex(int i) {
return stacks[i];
}
You are returning a copy of the stack at [i] when you call
Stack Stacks::getStackAtIndex(int i);
this means you aren't actually operating on the stack at that index but a completely new one that is constructed by copying the data from the stack you want. Just change the return value from
Stack
to
Stack&
Also try not to use namespace std, you will be surprised how many things you use are actually in that namespace. It may overwhelm you if you are ever forced to avoid using it.
Additionally i have noticed you used
int N;
as both a data member in Stack and a parameter in
void Stack::add(int);
i would change this.

Exception Handling with pointer [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
how to handle the exception caused in this case using try-catch block. please help . thanks
double **pDblArray = 0;
pDblArray = new double *[5000000];
for(int i=0; i<5000000; i++)
{
pDblArray [i] = new double [5000000];
}
cout << "Completed Allocated" << endl;
Assuming you have enough memory:
try {
std::vector<std::vector<double>> vec(5000000, std::vector<double>(5000000));
// …
} catch (std::bad_alloc const& e) {
// …
}
I don't know the name of the particular exception for memory allocation overrun. Look that up.
double **pDblArray = 0;
pDblArray = new double *[5000000];
try
{
for (int i = 0; i < 5000000; i++)
{
pDblArray [i] = new double [5000000];
}
}
catch (std::bad_alloc const &e)
{
cout << "Boom! " << endl;
}

Stack unwinding [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I was told that putting all pointers in the catch block is bad OO programming. Cleanup occurs in the catch block. How does it violate every rule of OO design?
Here is a sample code:
#include <iostream>
#include <string>
using namespace std;
class Error
{
friend int main();
public:
Error(int* p, string m) : arr(p), msg(m) { }
private:
int* arr;
string msg;
};
void initialize();
int main()
{
try {
initialize();
}
catch(Error& err) {
cout<<endl<< "Error! "<< err.msg <<endl<<endl;
delete [] err.arr;
}
return 0;
}
void initialize()
{
int size;
cout<<"Enter the number of elements: ";
cin >> size;
int* myArray = new int[size];
cout<<"Enter the elements: " <<endl;
for (int i=0; i<size; ++i)
cin >> myArray[i];
if (!cin.good())
throw Error(myArray, (string)"bad input!");
cout<<endl<<"You entered:"<<endl;
for (int i=0; i<size; ++i)
cout << myArray[i] << " ";
cout<<endl;
delete [] myArray;
}
Please ignore this line. I'm just trying to get this question posted.
To deal with resources, C used to focus on managing the execution paths. the programmer had to make sure that for every possible path, the resources were freed.
So it was normal to end with code like that :
Notice that most of the code is there to handle error(s).
HRESULT
CreateNotifyIcon(NotifyIcon** ppResult)
{
NotifyIcon* icon = 0;
Icon* inner = 0;
const wchar_t * tmp1 = 0;
HRESULT hr = S_OK;
if ( SUCCEEDED(hr) ) {
icon = new (nothrow) NotifyIcon();
if ( !icon ) hr = E_OUTOFMEM;
}
if ( SUCCEEDED(hr) )
hr = icon->set_text("Blah blah blah");
if ( SUCCEEDED(hr) ) {
inner = new (nothrow) Icon(...);
if ( !inner )
hr = E_OUTOFMEM;
else {
Info info;
hr = GetInfo( &info );
if ( SUCCEEDED(hr) )
hr = icon->set_icon(inner, info);
if ( SUCCEEDED(hr) )
inner = NULL;
}
}
if ( SUCCEEDED(hr) )
hr = icon->set_visible(true);
if ( SUCCEEDED(hr) ) {
*ppResult = icon;
icon = NULL;
} else {
*ppResult = NULL;
}
cleanup:
if ( inner ) delete inner;
if ( icon ) delete icon;
return hr;
}
In C++, this is not the right way because you have exceptions. For instance :
String EvaluateSalaryAndReturnName( Employee e )
{
if( e.Title() == "CEO" || e.Salary() > 100000 )
{
cout << e.First() << " " << e.Last()
<< " is overpaid" << endl;
}
return e.First() + " " + e.Last();
}
There are 23 different execution paths in that snippet of code.
So C++ chose to focus on the resources instead. Each function (should) handle a limited number of resources. Roughly speaking, you put a watchdog on each resource to make sure they are properly released/freed. This watch dog is RAII. Indeed, whatever the execution path may be, you are 100% sure the destructor of all objects allocated on the stack will be called. That way, by putting your resources into RAII object (STL containers, std::unique_ptr,...), you can deal with exceptions without any problem of leaked resource.
Look at the difference :
BAD WAY
void function(int n){
int* p = 0;
int* c = 0;
try{
p = new int[n];
c = new int[n*2];
}
catch(std::exception const& e){
delete[] c;
delete[] p;
throw;
}
delete[] c;
delete[] p;
}
int main(){
try{
function(1000);
} catch (std::exception const& e){
std::cerr<<e.what()<<std::endl;
}
}
GOOD WAY
void function(int n){
std::unique_ptr<int[]> p(new int[n]); //or std::vector
std::unique_ptr<int[]> c(new int[n*2]);
}
int main(){
try{
function(1000);
} catch (std::exception const& e){
std::cerr<<e.what()<<std::endl;
}
}
The problem is, that you have to delete the array in all possible ways to leave the function. This may be easy if you have only one or two ways, but gets confusing with more. Even in your code you have one delete already outside the function, what it makes hard to find.
Use smart pointers to target that issue. They deallocate their content when they get out of scope. That way you don't have to bother for the destruction of the array. As soon as the function is done, the array will be destroyed.
Here is some documentation for smart pointers:
unique_ptr
shared_ptr
The C++ Standard n3337 § 15.2/3 says:
The process of calling destructors for automatic objects constructed
on the path from a try block to a throw-expression is called “stack
unwinding. (...)”
The problem with your code is that pointer to array is allocated inside try block, so it is no longer alive when control reaches catch block. You cannot do
To correct this you should declare a pointer before try block:
int* myArray;
try{
function(1000); // allocate an array and point myArray to it
} catch (std::exception const& e){
delete [] myArray; // OK, myArray pointer is valid here
}
This will delete the objects and return memory to the system. Such approach is taken for example in std::uninitialized_fill. But you got the better possibility. To free yourself from the burden of deallocating memory you can consider using smart pointer or a handle to an array (a class that wraps around a resource): representing each resource as a class is the foundation of approach called RAII.
try{
MyArray myArray(1000); // allocate an array in constructor
} catch (std::exception const& e){
// destructor for myArray has deleted ints & returned memory already
}