Thread: Defensive programming?

  1. #16
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    argv is a vector of char *, right so, you want argv[1] for example.

    --
    Mats

  2. #17
    Internet Superhero
    Join Date
    Sep 2006
    Location
    Denmark
    Posts
    964
    Quote Originally Posted by Daved View Post
    >> Wouldn't it be easier to just set int n to a very large value before i call new? Wouldn't this generate the same result?

    Maybe, but it sounded like you tried the largest int possible and it still didn't cause a memory allocation error. If you didn't try the largest int possible, try it. Chances are that will be 2147483647. Or switch to unsigned and try 4294967295. If neither of those cause a memory allocation error, then you cannot test it without changing your code.
    I changed n to 2147483647 just before the new call, and i got the memory overflow error and the program exited correctly, so the overflow check is working correctly

  3. #18
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Good. I was confused earlier because I assumed when you overflow the int atoi just left it as the largest possible value, which was obviously an incorrect assumption.

  4. #19
    Registered User
    Join Date
    Sep 2006
    Posts
    835
    Quote Originally Posted by Daved View Post
    >> Wouldn't it be easier to just set int n to a very large value before i call new? Wouldn't this generate the same result?

    Maybe, but it sounded like you tried the largest int possible and it still didn't cause a memory allocation error. If you didn't try the largest int possible, try it. Chances are that will be 2147483647. Or switch to unsigned and try 4294967295. If neither of those cause a memory allocation error, then you cannot test it without changing your code.
    Shouldn't it be the largest possible value of a std::size_t, i.e.

    static_cast<std::size_t>(-1)

  5. #20
    Internet Superhero
    Join Date
    Sep 2006
    Location
    Denmark
    Posts
    964
    Quote Originally Posted by matsp View Post
    argv is a vector of char *, right so, you want argv[1] for example.

    --
    Mats
    Yeah that makes sense. I corrected the code and it's all working perfectly now, if i input something like "main.exe 23498723598724985729857", strtol() sets n to LONG_MAX and new overflows, so i get the overflow error and the program exits correctly

    Thanks alot matsp and Daved, great help!

    By the way, why would anyone use atoi() when strtol() does the same AND checks for overflow?

    Edit: Oh, and one last question, would it be better if i didn't use std::nothrow and used the exceptions correctly, does it matter in a small program like this?
    Last edited by Neo1; 08-09-2007 at 05:34 PM.

  6. #21
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    I think the reason atoi exists at all is that it was created (a long time) before strtol().

    As I described, you can actually check if the number overflowed by looking at "errno" after strtol() - not that it REALLY makes much difference if someone entered some huge number...

    --
    Mats

  7. #22
    Internet Superhero
    Join Date
    Sep 2006
    Location
    Denmark
    Posts
    964
    Quote Originally Posted by matsp View Post
    I think the reason atoi exists at all is that it was created (a long time) before strtol().

    As I described, you can actually check if the number overflowed by looking at "errno" after strtol() - not that it REALLY makes much difference if someone entered some huge number...

    --
    Mats
    And 'errno' is some variable defined in cstdlib? Actually, i just realized that i had forgotten to include cstdlib, isn't that where strtol and atoi and all that are declared?

  8. #23
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Oh, and how is my program style-wise
    If you add using namespace std; after your #includes you don't need to prepend std:: all over the place.

    You could use std::auto_ptr or some other smart pointer to prevent memory leaks. i.e.:
    Code:
    auto_ptr<int> Input_ptr( new (std::nothrow) int[n] );
      // instead of:
    Input_ptr = new (std::nothrow) int[n];
    Then you'd have to remove your own delete [] code since the auto_ptr will delete it for you.

    Get rid of all those nasty C-functions and use std::stringstream:
    Code:
    stringstream str;
    str << argv[1];
    unsigned int n = 0;
    str >> n;
    
    if ( str.fail() == true )
    {
        cout << "Error converting argv[1] to unsigned int!" << endl;
    }
    Originally Posted by matsp
    argv is a vector of char *, right so, you want argv[1] for example.
    Not exactly. It's an array of char*

  9. #24
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    If you add using namespace std
    This will make a programming style worse not better
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  10. #25
    Registered User MacNilly's Avatar
    Join Date
    Oct 2005
    Location
    CA, USA
    Posts
    466
    Quote Originally Posted by Neo1 View Post
    I tried this code instead of my orignal using atoi():

    Code:
    n = strtol(argv, NULL, 10);
    /* Check to see whether or not the first parameter is a number greater than 0 */
    if(!n)
    {
    		std::cerr << "Wrong parameters, please input a number greater than 0." << std::endl;
    		exit(1);
    }
    	
    /* Allocate memory according to input from commandline */
    Input_ptr = new (std::nothrow) int[n];
    Code:
    /* Check to see whether or not the first parameter is a number greater than 0 */
    if(!n)
    Bad. What if n is negative? The loop condition will be false and you will then attempt to allocate a negative number of objects on the heap. Bad things could happen.

    If you want to "Check to see whether or not the first parameter is a number greater than 0" then do just that.

  11. #26
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    vart: This will make a programming style worse not better
    If you put it in a header file or before an #include you are right, but other than that it's perfectly fine.

  12. #27
    Internet Superhero
    Join Date
    Sep 2006
    Location
    Denmark
    Posts
    964
    Quote Originally Posted by cpjust View Post
    If you put it in a header file or before an #include you are right, but other than that it's perfectly fine.
    I'm gonna have to disagree with you on that one, when using namespace std; you bring each name and symbol from the std namespace into scope, so if i use a name for a function or variable that is in the std namespace, without me knowing it, it might lead to some clashes. I thought a bit about using "using std::cin" and "using std::cout" but i just think my code looks alot prettier the way it is now...
    Last edited by Neo1; 08-12-2007 at 12:27 PM.

  13. #28
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by Neo1 View Post
    I'm gonna have to disagree with you on that one, when using namespace std; you bring each name and symbol from the std namespace into scope, so if i use a name for a function or variable that is in the std namespace, without me knowing it, it might lead to some clashes.
    As the doctor says, "Then don't do that."

    If "using namespace" was universally bad, it would not have been put in the language. When I use it, I tend to use it within a function scope, not module scope:

    Code:
    void some_function()
    {
        using namespace std;
    
        ...
    }
    Keeping it at the function level makes it easier to apprehend all the names which might be used and therefore makes clashes much less likely.

    At any rate, reusing a name from std:: is a bad idea. Namespaces weren't invented to be a pain in the ass, making you type std:: everywhere. They were invented to help avoid name clashes between external libraries. In my opinion, std:: should not have been created in the first place -- it all should have gone into the global namespace.

  14. #29
    Internet Superhero
    Join Date
    Sep 2006
    Location
    Denmark
    Posts
    964
    Quote Originally Posted by brewbuck View Post
    As the doctor says, "Then don't do that."

    If "using namespace" was universally bad, it would not have been put in the language. When I use it, I tend to use it within a function scope, not module scope:
    I never said it was universally bad did i? Correct me if i'm wrong but i believe that the reason it was put in the language is so that you don't have to type out std:: all over the place when recompiling legacy code. Why put a bunch of functions into the scope if you're only going to be using maybe 5 or 6 of them anyways, imho, if you're going to be "using" anything, only do it with the stuff that you're actually planning on putting in your code, like "using std::string" and "using std::swap" and so on.

  15. #30
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    It will only clash with names that you #include. If you only #include <iostream> and decide to use variables named 'string' (a bad idea since you might decide to use STL strings in the future) then there won't be any problems.

    If you do have name conflicts (extremely unlikely in my experience) then you have two choices:
    • Rename your variable or function to something else.
    • Explicitly specify the namespace that the name belongs to (std:: or whatever:: )

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. help please.. linkedlists/classes
    By swayp in forum C++ Programming
    Replies: 10
    Last Post: 01-18-2005, 05:14 PM
  2. Segmentation fault with structs and char pointers
    By Keybone in forum C++ Programming
    Replies: 20
    Last Post: 01-17-2004, 01:36 PM
  3. Bowling for Columbine
    By Silvercord in forum A Brief History of Cprogramming.com
    Replies: 97
    Last Post: 09-09-2003, 07:48 PM