Thread: gdb/C atoi confusion

  1. #1
    Old Fashioned
    Join Date
    Nov 2016
    Posts
    137

    Question gdb/C atoi confusion

    I'm trying to parse a command-line argument for a -p option using getopt. This is what I'm getting in gdb though:

    Code:
    (gdb) print port_number
    No symbol "port_number" in current context.
    (gdb) step
    handle_input (argv=0x7fffffffde68, argc=4)
        at /home/me/Desktop/programs/scanr/src/scanr.c:44
    44      while ((c = getopt (argc, argv, "t:ip:l:u:o:vh")) != -1)
    (gdb) print port_number
    $5 = <optimized out>
    (gdb) step
    46        switch (c)
    (gdb) print port_number
    $6 = <optimized out>
    (gdb) step
    59            port_number = atoi(optarg);
    (gdb) 
    atoi (__nptr=<optimized out>) at /usr/include/stdlib.h:241
    241      return (int) strtol (__nptr, (char **) NULL, 10);
    (gdb) p port_number
    No symbol "port_number" in current context.
    (gdb) p optarg
    $7 = 0x7fffffffe1dc "555"
    What's going on is that port_number is initialized to 0 at the the start of the function, but when someone passes -p [portnumber], port_number is then supposed to be set to that number. However, something is happening as you can see, where atoi(optarg) is not setting port_number properly.. I'm guessing it's something with the __nptr=<optimized out> and line below that but I'm not really sure. You can see how port_number disappears from scope but that optarg is indeed set to the proper port number as specified with option -p. See code:


    Code:
    static void handle_input(int argc, char **argv)
    {
      int port_number = 0;
      int t_flag = 0;
      int i_flag = 0;
      int p_flag = 0;
      int l_flag = 0;
      int u_flag = 0;
      int o_flag = 0;
      int v_flag = 0;
      int h_flag = 0;
    
      char *cvalue = NULL;
      int index;
      int c;
    
      int opterr = 0;
    
      while ((c = getopt (argc, argv, "t:ip:l:u:o:vh")) != -1)
      {
        switch (c)
          {
          case 't':
            t_flag = 1;
            int threads_count = atoi(optarg);
            /*TODO: Add validation*/
            break;
          case 'i':
            i_flag = 1;
            break;
          case 'p':
            p_flag = 1;
            /*get the argument supplied to p*/
            port_number = atoi(optarg);
            if(!validate_port_number(port_number)){
              printf(INVALID_PORT);
              return;
            }
            break;
          case 'l':
            l_flag = 1;
            int port_number_lower = atoi(optarg);
            if(!validate_port_number(port_number_lower)){
              printf(INVALID_PORT);
              return;
            }
            break;
          case 'u':
            u_flag = 1;
            int port_number_upper = atoi(optarg);
            if(!validate_port_number(port_number_upper)){
              printf(INVALID_PORT);
              return;
            }
            break;
          case 'o':
            o_flag = 1;
            int conn_timeout_seconds = atoi(optarg);
            /*TODO: Add validation*/
            break;
          case 'v':
            printf("scanr %s\n", SCANR_VERSION);
            printf("License MIT: The MIT License <https://opensource.org/licenses/MIT>\n");
            exit(1);
            break;
          case '?':
            if (optopt == 'o' || optopt == 'p'
             || optopt == 'l' || optopt == 'u'
             || optopt == 't'){
              fprintf (stderr, "Option -%c requires an argument.\n", optopt);
            }
            else if (isprint (optopt)){
              fprintf (stderr, "Unknown option `-%c'.\n", optopt);
            }
            else{
              fprintf (stderr,
                       "Unknown option character `\\x%x'.\n",
                       optopt);
            }
    
          case 'h':
          default:
              ui_print_help();
              exit(1);
              break;
          }
        }
      }
    
    static bool validate_port_number(int number)
    {
      return (number > 65535 || number < 1) ? true : false;
    }
    The only thing I could guess is, am I not using atoi properly? Not sure what's going on here. Thanks.

    PS: On Linux (Fedora 25)
    Last edited by Asymptotic; 02-08-2017 at 09:41 PM.

  2. #2
    Registered User
    Join Date
    Jun 2015
    Posts
    1,643
    port_number is basically useless since it's a local variable that you can't access outside the function. Usually a general program parameter value like that would be global. It's been optimized out since its only use is to pass to the validation function (which is probably inlined due to its simplicity).

    If you want to know that atoi is "working" you could add a printf after it to print port_number.

    "handle_input" is a strange name for processing command line parameters. That's not usually called "input".

    If you want your parameters to be useful, you should make a global structure containing the variables that you set based on them. This is a case where a global variable is a good thing. Those names are pretty bad, though (e.g, what does i_flag mean?). Better to have names like "thread_count", etc. And some of them are probably useless, like p_flag, l_flag, etc, since the actual value parameters are what you will presumably use, like port_number_lower, etc..
    Code:
    struct {
      int threads_count;
      int i_flag;          // give this a proper name
      int port_number;
      int port_number_lower;
      int port_number_upper;
      //etc...
    } param = {
        1,           // default thread_count
        0,            // default i_flag
        0,           // default port_number (???)
        //etc...
    };

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    37,998
    What compiler options did you use?
    Code:
    $ gcc -g foo.c
    $ gdb -q ./a.out
    Reading symbols from ./a.out...done.
    (gdb) b 50
    Breakpoint 1 at 0x40088a: file foo.c, line 50.
    (gdb) run -p 1234
    Starting program: /home/sc/Documents/a.out -p 1234
    
    Breakpoint 1, handle_input (argc=3, argv=0x7fffffffded8) at foo.c:50
    50	        if(!validate_port_number(port_number)){
    (gdb) print port_number
    $1 = 1234
    (gdb)
    Compare with
    Code:
    $ gcc -g -O2 foo.c
    $ gdb -q ./a.out
    Reading symbols from ./a.out...done.
    (gdb) b 50
    Breakpoint 1 at 0x40072b: file foo.c, line 50.
    (gdb) run -p 1234
    Starting program: /home/sc/Documents/a.out -p 1234
    
    Breakpoint 1, handle_input (argv=0x7fffffffded8, argc=3) at foo.c:50
    50	        if(!validate_port_number(port_number)){
    (gdb) p port_number
    $1 = <optimised out>
    If you want a full debug experience, then don't add any of the optimisation flags.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. HELP WITH atoi()
    By dhoow in forum C Programming
    Replies: 5
    Last Post: 12-10-2015, 12:09 PM
  2. use of atoi.
    By mgracecar in forum C Programming
    Replies: 3
    Last Post: 03-06-2012, 09:02 PM
  3. C++.NET Can I use atoi ??
    By Swaine777 in forum C++ Programming
    Replies: 3
    Last Post: 09-18-2004, 06:54 PM
  4. atoi()
    By Unregistered in forum C Programming
    Replies: 17
    Last Post: 07-13-2002, 02:09 AM

Tags for this Thread