CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 12 of 12
  1. #1
    Join Date
    Jun 2015
    Posts
    175

    Some serious error

    Hi guys,

    I'm reading a C++ book and in a chapter it gives me this code:

    Code:
    #include <C:\Users\CS\Desktop\std_lib_facilities_4.h>
    using namespace std;
    
    //------------------------------------------------------------------------------
    
    template<class Iterator >
    Iterator high(Iterator first, Iterator last)
    // return an iterator to the element in [first:last) that has the highest value
    {
    	Iterator high = first;
    	for (Iterator p = first; p != last; ++p)
    		if (*high<*p) high = p;
    	return high;
    }
    
    //------------------------------------------------------------------------------
    
    double* get_from_jack(int* count);  // jack puts doubles into an array
    									// and returns the number of elements
    									// in *count
    vector<double>* get_from_jill();    // Jill fills the vecto
    									
    //------------------------------------------------------------------------------
    
    void fct()
    {
    	int jack_count = 0;
    	double* jack_data = get_from_jack(&jack_count);
    	vector<double>* jill_data = get_from_jill();
    
    	double* jack_high = high(jack_data, jack_data + jack_count);
    	vector<double>& v = *jill_data;
    	double* jill_high = high(&v[0], &v[0] + v.size());
    	cout << "Jill's high " << *jill_high << ";  Jack's high " << *jack_high << endl;
    	// ... 
    	delete[] jack_data;
    	delete jill_data;
    }
    
    //------------------------------------------------------------------------------
    
    int main()
    {
    	fct();
    	system("pause");
    	return 0;
    }
    
    //------------------------------------------------------------------------------
    
    double* get_from_jack(int* count)
    {
    	if (!count)
    		return 0;
    
    	const int n = 10;
    
    	double* arr = new double[n];
    
    	if (arr)
    	{
    		*count = n;
    
    		for (int i = 0; i < n; ++i)
    			arr[i] = i;
    	}
    
    	return arr;
    }
    
    //------------------------------------------------------------------------------
    
    vector<double>* get_from_jill()
    {
    	const int n = 10;
    
    	vector<double>* arr = new vector<double>(n);
    
    	if (arr)
    	{
    		for (int i = 0; i < n; ++i)
    			(*arr)[i] = i;
    	}
    
    	return arr;
    }
    
    //------------------------------------------------------------------------------
    The author, who is Stroustrup, poses this Try This:
    Try This
    We again left a serious error in that program. Find it, fix it, and suggest a general remedy for that kind of problem.


    The code runs successfully. I tried but I'm not sure where that serious error is!
    Would you help me please?

  2. #2
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,824

    Re: Some serious error

    Just because a program seems to work OK with one set of data, doesn't mean the program is correct and doesn't contain errors. For testing, all paths through a program needs to be considered.

    What about if get_from_jack() returns 0?

    What about if new fails to allocate?
    Last edited by 2kaud; May 31st, 2016 at 03:21 AM.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  3. #3
    Join Date
    Jun 2015
    Posts
    175

    Re: Some serious error

    Thanks.
    I think both remarks you pointed to belong to the failure of new!
    So we can surpass it using (for example) an if statement:
    Code:
    if (get_from_jack(&jack_count))
    and (get_from_jill)

  4. #4
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,824

    Re: Some serious error

    Unless otherwise coded, if new fails then it throws an exception. Also what if get_from_jack() is passed 0 (or NULL/nullptr)?

    So the general remedy is?
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  5. #5
    Join Date
    Jun 2015
    Posts
    175

    Re: Some serious error

    Thanks. You apparently are teaching me techniques rather than just giving the answer. I appreciate it. These are my answers.

    First we remove the if conditions of post #3 and go on this way:
    1- In code
    Code:
     if (!count)
         return 0;
    since count is a pointer which is fed by int jack_count which has the value of 0. So count has some address eventually and the above if condition will not execute. To me, that if condition is even useless!

    2- Since in the case of passing an exception if new fails, so what I need is to catch it and terminate the program showing a related message. So I wrote try after main() and the code below at the end of main()

    HTML Code:
    catch (...)
    {
    	cerr << "An exception occurred. The program terminates!"<< endl;
    	system("pause");
    	return 1;
    }
    In the case of get_from_jill() too, there is the issue of throwing an exception which, of course, will be caught be the catch.

    Now the code is better, I think.

  6. #6
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,824

    Re: Some serious error

    1) If the if condition is removed, and count is NULL/nullptr then the dereference of count to assign n will produce an exception. Also note that the default for new is to throw an exception if an error occurs trying to allocate the required memory. Hence you don't need the test on arr following new as it will always be non-null. if you don't want an exception to be generated for new than nothrow needs to be specified. See http://www.cplusplus.com/reference/new/operator%20new/

    2) Yes, but your catch (...) catches all exceptions. I don't know how much exceptions have been described so far in the book, but you can specify different catch conditions and handle each different condition differently. You can also create your own exception conditions and throw them as required and then catch them. See http://www.cplusplus.com/doc/tutorial/exceptions/ eg. so you could create your own exceptions for jack and jill, catch each separately and display different error messages etc etc. You can also catch an exception and rethrow a different exception to the next outer level of catch!

    Note that exceptions should only be used for situations that are really exceptional and not normal issues - ie trying to open a file that doesn't exist is a normal issue and not an exception.

    Have fun!
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  7. #7
    Join Date
    Jun 2015
    Posts
    175

    Re: Some serious error

    >> If the if condition is removed, and count is NULL/nullptr then the dereference of count to as will produce an exception.

    What I think is that the value of int* count in double* get_from_jack(int* count) cannot be zero, because some address is sent by get_from_jack(&jack_count); so the if condition will not execute! Hence it's useless apparently.


    >> the default for new is to throw an exception if an error occurs trying to allocate the required memory. Hence you don't need the test on arr following new as it will always be non-null.

    Do you mean — by the above test — that, when we use new for allocating memory for a variable like arr, in, for example, double* arr = new double[n];, the result will never be zero? So, isn't there any need to use a test like, if (arr) ?


    >> 2) Yes, but your catch (...) catches all exceptions. I don't know how much exceptions have been described so far in the book, but you can specify different catch conditions and handle each different condition differently. You can also create your own exception conditions and throw them as required and then catch them. See http://www.cplusplus.com/doc/tutorial/exceptions/ eg. so you could create your own exceptions for jack and jill, catch each separately and display different error messages etc etc.

    But both functions are dealing with bad_alloc message catchable by catch (exception& e). Why do we need different and separated catches?

    PS: I replaced catch(...) with catch(exception&) as you were right.

  8. #8
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,824

    Re: Some serious error

    The parameter of get_from_jack() is a pointer - so it can be null as any pointer can be null! What if someone used
    Code:
    int *cnt = nullptr;
    ....
    get_from_jack(cnt);
    meaning to set cnt somewhere in the code but forgot. Rather than having tests for null everywhere when a pointer shouldn't be null (note there are situations when passing null for a pointer is valid and in these circumstances a null test is needed) then exception code can be used.

    The result of using new as in your example will never be zero unless nothow is specified for new.
    Code:
    double * arr = new double[10];
    arr will never be null so there is no need for any test.

    Code:
    double * arr = new (nothrow) double [10];
    if (arr == nullptr) 
    //error in allocating memory
    In this case arr can be null so a test is needed.

    This need to test the return value for memory allocation comes from c programs where new isn't available. In c there is calloc()/malloc() (and free() to free used memory) to allocate memory which do return 0 if the allocation fails. Note that calloc()/malloc() can be used in c++ programs if the cstdlib header file is included but their use in c++ programs is not recommended.


    Whether you need different and separated catches is down to the program requirements!
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  9. #9
    Join Date
    Jun 2015
    Posts
    175

    Re: Some serious error

    Thanks 2Kaud for the explanations.
    So the general remedy for this particular Try This exercise, is to put a try-catch block for the main() function, as in this way:

    Code:
    int main() try
    {
    	fct();
    	system("pause");
    	return 0;
    }
    
    catch (exception& e)
    {
    	cout << "Standard exception: " << e.what() << endl;
    }
    Do you agree?

  10. #10
    Join Date
    Jun 2009
    Location
    France
    Posts
    2,513

    Re: Some serious error

    I wouldn't really agree. When an allocation fails, there isn't really anything you can do about it most of the time, and are usually better off just letting the exception propagate.

    In particular, I would NOT put a try catch around main.

    The only thing this would achieve is that any calling process would be tricked into thinking your main exited successfully. Also, you probably want to output to stderr. You *could* return EXIT_FAILURE, but at that point, you're just replicating the behavior of just letting the exception escape. So you might as well just do nothing.

  11. #11
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,824

    Re: Some serious error

    Or like this which would then catch all exceptions. How you handle exceptions is really down to the program requirements - whether you need to catch specific exceptions or if a general catch-all will do. The important point is that in 'proper' production code then exceptions need to be handled properly and to not let the program 'crash'. Most of the example code posted in forums like this are not of production quality and so don't consider exceptions and every error condition that could arise. In production code every eventuality needs to be handled properly. Every time you use a function you need to know how that function reports errors and how your code is going to deal with it.

    Code:
    int main()
    {
    	try
    	{
    		fct();
    	}
    
    	catch (exception& e)
    	{
    		cout << "Standard exception: " << e.what() << endl;
    	}
    
    	catch (...)
    	{
    		cout << "Unknown exception" << endl;
    	}
    
    	system("pause");
    	return 0;
    }
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  12. #12
    Join Date
    Jun 2015
    Posts
    175

    Re: Some serious error

    Thank you two very much.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured