mardi 28 mars 2017

Incorrect results when dereferencing boost::optional directly from a return value

This problem occurs for me on GCC 4.4.7, specifically g++ 4.4.7 20120313 (Red Hat 4.4.7-17). I've tried it under both clang 3.8 and GCC 4.8.4 and do not have the same problem. Boost version is boost 1.55. The minimal example:

example.hpp

#pragma once

#include <boost/optional.hpp>

struct baz 
{
private:

    boost::optional<int> x;

public:

    void f(int bar)
    {   
        if(bar < 10) { x = bar * 5; }
    }   

    boost::optional<int> foo()
    {   
        return x;
    }   
};

example.cpp

#include "example.hpp"

#include <iostream>
#include <memory>


int quux(baz& b)
{
    int t = 0;
    if(b.foo()) {
        t = *(b.foo());
    }   
    std::cout << *(b.foo()) << '\n';
    return t;
}


int main()
{
    std::unique_ptr<baz> b(new baz);
    b->f(5);
    int i = quux(*b);
    std::cout << i << '\n';
}

This is compiled as g++ example.cpp -std=c++0x -Wall -Wextra -O2 -o bot (note that it also fails under -O3, but not under O0 or O1).

Expected output is:

25
25

Actual output is:

0
0

Note that using a less silly code variant for quux does work:

// This gives the expected output
int quux(baz& b)
{
    int t = 0;
    auto f = b.foo();
    if(f) {
        t = *f; 
    }   
    std::cout << *f << '\n';
    return t;
}

Is it possible this is caused by a strict aliasing issue? Or is there something else going on here I'm missing?

Edit:

When not using unique_ptr:

int main()
{
    baz b;
    b.f(5);
    int i = quux(b);
    std::cout << i << '\n';
}

Results are:

0
32766

Aucun commentaire:

Enregistrer un commentaire