boost :: program_options генерирует MLK.MUST в Klocwork - PullRequest
0 голосов
/ 04 августа 2020

Я написал следующий код C ++ на основе библиотеки Boost для ввода данных из командной строки.

#include <iostream>
#include <boost/program_options.hpp>
#include <boost/format.hpp>

using namespace std;
namespace po = boost::program_options;

int main(int argc, char** argv) {
    int party = 2, port = 9999;
    string server_ip;
    
    po::options_description desc{"Allowed options"};
    desc.add_options()  //
    ("help,h", "produce help message")  //
    ("party,k", po::value<int>(&party)->default_value(1), "party id: 1 for server, 2 for client")  //
    ("port,p", po::value<int>(&port)->default_value(1234), "socket port")  //
    ("server_ip,s", po::value<string>(&server_ip)->default_value("localhost"), "server's IP.");
    
    po::variables_map vm;
    try {
        po::parsed_options parsed = po::command_line_parser(argc, argv).options(desc).allow_unregistered().run();
        po::store(parsed, vm);
        if (vm.count("help")) {
            cout << desc << endl;
            return 0;
        }
        po::notify(vm);
    }catch (po::error& e) {
        cout << "ERROR: " << e.what() << endl << endl;
        cout << desc << endl;
        return -1;
    }
    
    cout << party << endl;
    cout << port << endl;
    cout << server_ip << endl;
}

Он работает как задумано. Однако Klocwork сообщил о следующей ошибке (я изменил номера строк для этого фрагмента кода):

main.cpp:16 MLK.MUST (2:Error) Analyze
Memory leak. Dynamic memory stored in 'po::value<int> ( &party)' allocated through function 'value<int>' at line 14 is lost at line 16
  * main.cpp:14: Dynamic memory stored in 'po::value<int> ( &party)' is allocated by calling function 'value<int>'.
    * value_semantic.hpp:198: 'r' is allocated by function 'new'.
  * main.cpp:16: Dynamic memory stored in 'po::value<int> ( &party)' is lost.
Current status 'Analyze'

Я нашел этот старый пост boost program_options, генерирующий Klocwork MLK. ОБЯЗАТЕЛЬНО . Однако, прочитав ответ, я все еще не знаю, как решить эту проблему.

Другая проблема, о которой сообщает Klocwork, - 'port' is used uninitialized in this function. В нем конкретно упоминается, что passing '&port' to 'po::value<int>' does not initialize 'port'. Однако после запуска кода я вижу, что он инициализирует порт, поскольку значение порта печатается как 1234, а не 9999.

Есть ли способ написать этот код, который решит указанные выше проблемы?

1 Ответ

1 голос
/ 05 августа 2020

Еще одна проблема, о которой сообщает Klocwork, заключается в том, что в этой функции используется неинициализированный порт. В нем конкретно упоминается, что передача '& port' в 'po :: value'

Это ложное срабатывание: ничто не использует значение port до его инициализации (я проверил). Однако этого должно быть достаточно для фактической инициализации port, чтобы отключить сообщение. Странно, что он все еще срабатывает, раз уж он у вас уже был.

Ни vaglrind, ни ASAN + UBSAN не нашли для меня ничего плохого в коде. Вот тест грубой силы, который пробует все виды комбинаций опций (включая незарегистрированные и ошибочные):

#!/bin/bash
set -e -u
opts=( '' '-k two' '-k 2' '-p 2345' '-s 127.0.0.88' 'bogus' '--more-bogus');
for a in "${opts[@]}"
do
    for b in "${opts[@]}"
    do
        for c in "${opts[@]}"
        do
            valgrind ./sotest "$a" "$b" "$c"
        done
    done
done

В результате выполняется 343 различных вызова программы и выводятся ожидаемые результаты:

 69x 2
 69x 2345
 69x 127.0.0.88

 99x 1
 99x 1234
 99x localhost

Ожидаемая диагностика:

 17x option '--port' cannot be specified more than once
 17x option '--server_ip' cannot be specified more than once
 34x option '--party' cannot be specified more than once
107x the argument ('two') for option '--party' is invalid

И, самое главное, последовательный отчет об отсутствии утечек:

343 All heap blocks were freed -- no leaks are possible

TL; DR

Я не знать, почему ваш инструмент сообщает об утечках. По крайней мере, "'порт' используется неинициализировано" проблема при ближайшем рассмотрении кажется неправильной.

Я тестировал G CC 10 с Boost 1.73.0, -std = c ++ 17 -O3, ваш исходный код 1 -% без изменений.

Надеюсь, это даст вам больше идей и, возможно, некоторых утешений.

...