CLI11 icon indicating copy to clipboard operation
CLI11 copied to clipboard

One option without adding any

Open rimmartin opened this issue 3 years ago • 4 comments

Pulled CLI11 yesterday and today. Starting a small app

int main(int argc, char **argv)
{
    std::cout<<"main "<<std::endl;
    CLI::App app{"QMechanic"};
    app.parse(argc, argv);
    std::cout << "app.parsed:" << std::endl;
    std::cout<<"get_options size "<<app.get_options().size()<<std::endl;
    return EXIT_SUCCESS;
}

running ./main results in

get_options size 1

There is already one option? If code is added to iterator over

        for(std::vector< CLI::Option*>::const_iterator it=app.get_options().cbegin();it!=app.get_options().cend();++it){
                std::cout<<"Option ";
                std::cout<<std::endl;
        }

the iteration happens once and see the "Option ".

If count(or other members such as has_description()) is checked a crash happens

        for(std::vector< CLI::Option*>::const_iterator it=app.get_options().cbegin();it!=app.get_options().cend();++it){
            if((*it)->count()>0){
                std::cout<<"Option ";
                std::cout<<std::endl;
            }
        }

If one option is coded the number of options is 2 and the crashes still happen. If a counter is added to skip the first option returned by the const_iterator then no crash and have access to members such as has_description and get_description.

Iterating with it++ instead of ++it yields different behavior but still crashes.

rimmartin avatar Aug 03 '22 13:08 rimmartin

Oh compile lines are:

g++ -fPIE -std=c++17 -I../working-copyDevCLI11/CLI11/include -Wl,--allow-multiple-definition -MT main.o -MMD -MP -O3 -c -o main.o main.cpp
g++  -pie -Wl,--allow-multiple-definition  -o main main.o -lm -lpthread -lz -lstdc++ -ldl -lrt

rimmartin avatar Aug 03 '22 13:08 rimmartin

Quick comment; that's the wrong way to run the parse. It should be:

try {
    app.parse(argc, argv);
} catch (const CLI::ParseError &e) {
    return app.exit(e);
}

(or use the CLI11_PARSE macro). If there's an error, that will exit nicely.

The one option is -h/--help. You can remove it, but it's there by default.

You are not iterating over correctly - ~~you are dereferencing twice~~, you are calling get_options() twice and comparing, which is the crash. Here's a working example:

// This file is a "Hello, world!" CLI11 program

#include "CLI11.hpp"
#include <iostream>
#include <string>

int main(int argc, char **argv)
{
    std::cout<<"main "<<std::endl;
    CLI::App app{"QMechanic"};
    CLI11_PARSE(app, argc, argv); // Nicer, but worked the old way as long as no error was thrown
    std::cout << "app.parsed:" << std::endl;
    std::cout << "get_options size " << app.get_options().size() << std::endl;

    for(const auto&& it : app.get_options()){
        std::cout << it->get_name() <<  " " << std::endl;
        if(it->count() > 0){
            std::cout << "Option ";
            std::cout << std::endl;
        }
    }
    
    return EXIT_SUCCESS;
}


henryiii avatar Aug 03 '22 17:08 henryiii

@henryiii they are not "dereferencing twice" - they just iterate the old style - with an iterator that itself needs to be dereferenced. I think you're referring to a fact, that App::get_options() returns vector by value, so they are comparing iterators from many different vectors, and nothing good can come out of that.

jzakrzewski avatar Aug 03 '22 18:08 jzakrzewski

Ahh, yes, you call get_options twice, so the begin and end are incorrect. I would recommend using C++11 style iteration if you are in C++17, not C++98. The copy is made because that's not actually how the data is stored, they are actually a vector of unique pointers.

henryiii avatar Aug 03 '22 18:08 henryiii