0

我基于 Boost 库编写了以下 C++ 代码,以从命令行获取输入。

#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.MUST。但是,阅读答案后,我仍然不知道如何解决这个问题。

Klocwork 报告的另一个问题是'port' is used uninitialized in this function. 它特别提到passing '&port' to 'po::value<int>' does not initialize 'port'. 但是,在运行代码后,我看到它确实初始化了端口,因为端口的值打印为 1234 而不是 9999。

有没有办法编写这段代码来解决上述问题?

4

1 回答 1

1

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;博士

我不知道为什么您的工具报告泄漏。至少,仔细检查后, “'port' is used uninitialized”问题似乎是错误的。

我在 GCC 10 上使用 Boost 1.73.0 进行了测试,-std=c++17 -O3,你的源代码 1--% 没有改变。

我希望这能给你更多的想法,也许会给你一些保证。

于 2020-08-05T01:17:50.880 回答