Segfault in second call to getopt_long

Hi there,

i try to develop an application using googletest as a testing framework. To parse the programs arguments i use getopt_long from libc.

The first test (the first call of getopt_long) works fine. For the second and later tests, a segmentation fault happens.

Valgrind outputs:

==27905== Invalid read of size 8
==27905==    at 0x3AE46CE020: _getopt_internal_r (in /lib64/libc-2.12.so)
==27905==    by 0x3AE46CF1EA: _getopt_internal (in /lib64/libc-2.12.so)
==27905==    by 0x3AE46CF2D2: getopt_long (in /lib64/libc-2.12.so)
==27905==    by 0x402004: CMDOptions::parseCommandLineArguments(int, char**) (cmdoptions.cpp:28)
[...]
==27905== Invalid read of size 1
==27905==    at 0x3AE46CE024: _getopt_internal_r (in /lib64/libc-2.12.so)
==27905==    by 0x3AE46CF1EA: _getopt_internal (in /lib64/libc-2.12.so)
==27905==    by 0x3AE46CF2D2: getopt_long (in /lib64/libc-2.12.so)
==27905==    by 0x402004: CMDOptions::parseCommandLineArguments(int, char**) (cmdoptions.cpp:28)


The testcode looks like
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
TEST(TestOptionsClass, parseProvidedArguments)
{
  char **args = new char*[3];
  args[0] = (char*) "./prog";
  args[1] = (char*) "-ab";
  args[2] = (char*) "-f";
  CMDOptions *testObj1 = new CMDOptions(3, args);
  EXPECT_TRUE(testObj1->isForegroundSet());

  char **args2 = new char*[3];
  args2[0] = (char*) "./prog";
  args2[1] = (char*) "-ab";
  CMDOptions *testObj2 = new CMDOptions(2, args2);
  EXPECT_TRUE(testObj2->isForegroundSet());
}

While **char is on the heap, as i tried that to fix the problem without any effort.

and my application code like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
CMDOptions::CMDOptions(int argc, char **argv)
: isForeground(false)
{ 
  this->parseCommandLineArguments(argc, argv);
};

void CMDOptions::parseCommandLineArguments(int argc, char **argv)
{ 
  int character = 0;
  int option_index = 0;
  int verbose_flag = 0;
  struct option longopt[] = {
    /* These options set a flag. */
    {"verbose", no_argument,       &verbose_flag, 1},
    /**
    ** These options don't set a flag.
    ** We distinguish them by their indices.
    **/
    {"add",     no_argument,       0, 'a'},
    {"append",  no_argument,       0, 'b'},
    {"delete",  required_argument, 0, 'd'},
    {"create",  required_argument, 0, 'c'},
    {"foreground",   no_argument,  0, 'f'},
    {0, 0, 0, 0}
  };
  while((character = getopt_long(argc, argv, "abcfd", longopt, &option_index)) != -1){
    switch(character){
      case 'f':
        this->setForeground();
      break;
    }
  }
};

void CMDOptions::setForeground()
{ 
  this->isForeground = true;
}

bool CMDOptions::isForegroundSet()
{ 
  return this->isForeground;
};


Anyone has an idea how to fix that? Is it a problem in my code or in libc? What about calling getopt_long twice oder more often?

Thanks in advance
- atze
Hi all,

i found the solution by myself: getopt_long uses the global variables

extern int optind, opterr, optopt;

After the first call i set optind = 1; and everything is working again...

Thanks to http://pubs.opengroup.org/onlinepubs/009696799/functions/getopt.html

- atze
Last edited on
Unrelated
1
2
//CMDOptions *testObj1 = new CMDOptions(3, args);
CMDOptions testObj1 (3, args);
Topic archived. No new replies allowed.