Menu

False positive (access of moved variable) after failed try_emplace (std::unique_ptr, std::map)

Lila
10 hours ago
10 hours ago
  • Lila

    Lila - 10 hours ago

    If my understanding of try_emplace is correct, it doesn't move rvalue arguments in case of insertion failure.

    Unlike insert or emplace, these functions do not move from rvalue arguments if the insertion does not happen, which makes it easy to manipulate maps whose values are move-only types, such as std::map<std::string, std::unique_ptr<foo>>.
    https://en.cppreference.com/w/cpp/container/map/try_emplace

    Cppcheck reports "Access of moved variable" when I try to access std::unique_ptr in case of failure of the try_emplace.

    Code example:

    #include <iostream>
    #include <map>
    #include <memory>
    #include <stdint.h>
    
    int
    main (void)
    {
        std::map<uint32_t, std::unique_ptr<uint32_t>> m_map;
        auto req1 = std::make_unique<uint32_t>(321);
        auto req2 = std::make_unique<uint32_t>(4321);
    
        auto [it1, result1] = m_map.try_emplace(123, std::move(req1));
        if (result1 != true)
        {
            std::cout << "Failed to insert map, req1=" << *req1 << "\n";
            return 1;
        }
    
        std::cout << "Insertion OK, req1=" << *it1->second << "\n";
    
        auto [it2, result2] = m_map.try_emplace(123, std::move(req2));
        if (result2 != true)
        {
            std::cout << "Failed to insert map, req2=" << *req2 << "\n";
            return 1;
        }
    
        std::cout << "Insertion OK, req2=" << *it2->second << "\n";
        return 0;
    }
    

    Code compiling and running: g++ -std=c++20 test.cpp -o test && ./test

    Cppcheck command: cppcheck test.cpp --std=c++20 --enable=all --addon=threadsafety.py --inline-suppr --suppress=missingIncludeSystem

    Cppcheck output:

    Checking test.cpp ...
    test.cpp:16:56: warning: Access of moved variable 'req1'. [accessMoved]
            std::cout << "Failed to insert map, req1=" << *req1 << "\n";
                                                           ^
    test.cpp:13:50: note: Calling std::move(req1)
        auto [it1, result1] = m_map.try_emplace(123, std::move(req1));
                                                     ^
    test.cpp:16:56: note: Access of moved variable 'req1'.
            std::cout << "Failed to insert map, req1=" << *req1 << "\n";
                                                           ^
    test.cpp:25:56: warning: Access of moved variable 'req2'. [accessMoved]
            std::cout << "Failed to insert map, req2=" << *req2 << "\n";
                                                           ^
    test.cpp:22:50: note: Calling std::move(req2)
        auto [it2, result2] = m_map.try_emplace(123, std::move(req2));
                                                     ^
    test.cpp:25:56: note: Access of moved variable 'req2'.
            std::cout << "Failed to insert map, req2=" << *req2 << "\n";
    

    If I replace try_emplace with insert, I get segmentation fault.

     
  • CHR

    CHR - 10 hours ago
     

Log in to post a comment.

MongoDB Logo MongoDB