Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

boost::container::flat_map force_copy violates strict-aliasing rule #252

Closed
prus1337 opened this issue Aug 7, 2023 · 2 comments
Closed

Comments

@prus1337
Copy link

prus1337 commented Aug 7, 2023

Hi everyone!

g++ v13.1.0, v13.2.0, boost v1.82, MSYS2 MINGW64_NT-10.0-19044.

Discussion links:
msys2/MINGW-packages#17977
msys2/MINGW-packages#17977 (comment)

The following example has different behavior depending on compiler optimization flags:

#include <boost/container/flat_map.hpp>

#include <cstdint>
#include <iostream>
#include <string>

int main()
{
    boost::container::flat_map<std::string, size_t> map{};
    const std::string key = "test";
    const size_t value = 13;
	
    auto [it, succeeded] = map.emplace(key, value);
	
    if (succeeded)
    {
        std::cout << "emplace result: " << it->first << " -> " << it->second << "\n";
        std::cout << "emplace iterator result: " << "it == map.end() is " << std::boolalpha << (it == map.end()) << "\n";
		
        it = map.find(key);
        std::cout << "find result: " << it->first << " -> " << it->second << "\n";
        std::cout << "find iterator result: " << "it == map.end() is " << std::boolalpha << (it == map.end()) << "\n"; 
    }
	
    return 0;
}

Expected behavior

Without optimization flags (-O0, -O1) everything fine.
g++ -O0 -o boost_v1.82_flat_map_it_bug boost_v1.82_flat_map_it_bug.cpp

$ ./boost_v1.82_flat_map_it_bug
emplace result: test -> 13
emplace iterator result: it == map.end() is false
find result: test -> 13
find iterator result: it == map.end() is false

Actual behavior

With optimization flags (-O2, -O3) iterator has bad value.
g++ -O2 -o boost_v1.82_flat_map_it_bug boost_v1.82_flat_map_it_bug.cpp

./boost_v1.82_flat_map_it_bug
emplace result: test -> 13
emplace iterator result: it == map.end() is true
find result: test -> 13
find iterator result: it == map.end() is true

The issue does not happen in Linux with gcc 13.2.1 toolchain.

@Mark-MnetCS
Copy link

I bumped into a version of this problem that's reproducible on GCC trunk

#include <utility>
#include <boost/container/flat_map.hpp>

namespace bc = boost::container;

int main() {
    bc::flat_map<int, int> map {
        std::pair(0, 1),
        std::pair(1, 2),
        std::pair(2, 4)
    };

    if (map.size() != 3) {
        return 1;
    }

    int i = 0;
    for (const auto &[k, v] : map) {
        ++i;
    }
    if (i != 3) {
        return 2;
    }

    return 0;
}

When this is compiled with -O1 it runs as expected: i == 3 and the exit status is 0.
When compiled with -DBOOST_CONTAINER_DISABLE_FORCEINLINE -O2 the loop gets optimized away, i == 0 and the exit status is 2.

Here's a Compiler Explorer link showing the result: https://godbolt.org/z/7W5eGrKGE
Built with g++ (Compiler-Explorer-Build-gcc-181917d56c0cf4b8c1174a492a8157f4a12d1100-binutils-2.40) 14.0.0 20231219 (experimental)

gentoo-bot pushed a commit to gentoo/gentoo that referenced this issue Jun 3, 2024
Note that we have to crank the subslot for this. I've added a fudge .1
which we should drop on 1.86.0.

Closes: https://bugs.gentoo.org/933289
Bug: freeorion/freeorion#4949
Bug: boostorg/container#252
Bug: boostorg/container#281
Bug: https://bugs.gentoo.org/932780
Bug: https://bugs.gentoo.org/931587
Signed-off-by: Sam James <sam@gentoo.org>
@igaztanaga
Copy link
Member

Thanks for the report. The strict aliasing violation was needed only for ancient compilers so the following commit removes it for C++11 o newer:

20ad12f

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants