简体   繁体   中英

Visual C++ 2017 bug? Compiler optimizes away expression

The following piece of code has been causing me some issues, specifically the evaluation of diff:

#include <iostream>

template<typename T>
class array2d
{
protected:
    T* arr;
    int w, h;

public:
array2d() : arr(nullptr), w(0), h(0) {}

bool init(int w, int h)
{
    free();
    arr = new (std::nothrow) T[w*h];
    if (arr == nullptr)
    {
        std::cerr << "array2d::init(): Failed to allocate: " << w * h * sizeof(T) << " bytes.\n";
        return false;
    }
    this->w = w;
    this->h = h;
    return true;
}

void fill(T v)
{
    for (int i = 0; i < w*h; ++i)
        arr[i] = v;
}

void free()
{
    if (arr != nullptr)
    {
        delete[] arr;
        arr = nullptr;
        w = 0;
        h = 0;
    }
}

template<typename U>
bool copy(const array2d<U>& v)
{
    if (!v)
    {
        std::cerr << "array2d::copy(): Input array is empty.\n";
        return false;
    }
    if (w*h != v.width()*v.height())
    {
        if (!init(v.width(), v.height())) return false;
    }
    for (int i = 0; i < w*h; ++i)
        arr[i] = static_cast<T>(v(i));
    return true;
}

inline T operator()(int i) const { return arr[i]; }
inline T& operator()(int i) { return arr[i]; }
inline T operator[](int i) const { return arr[i]; }
inline T& operator[](int i) { return arr[i]; }
inline T operator()(int x, int y) const { return arr[x + y*w]; }
inline T& operator()(int x, int y) { return arr[x + y*w]; }

inline int width() const { return w; }
inline int height() const { return h; }
inline const T* get() const { return arr; }
inline T* get() { return arr; }

operator bool() const { return arr != nullptr; }

array2d<T>& operator*=(T v)
{
    for (int i = 0; i < w*h; ++i)
        arr[i] *= v;
    return *this;
}

~array2d() { free(); }
};

typedef unsigned long long uint64;

uint64 computeErrors(const array2d<uint64>& a, const array2d<uint64>& b)
{
    uint64 MNE = 0;
    for (int i = 0; i < a.height()*a.width(); ++i)
    {
        uint64 diff = ((a[i] >= b[i]) ? a[i] - b[i] : b[i] - a[i]);
        if (a[i] != b[i])
        {
            std::cout << "Diff: " << diff << "\n";
            std::cout << "What diff should equal to: " << ((a[i] >= b[i]) ? a[i] - b[i] : b[i] - a[i]) << "\n";
        }
        if (i == 0)
        {
            std::cout << "Diff should not be 0, but it is: " << diff << "\n";
        }
        if (MNE < diff)
        {
            MNE = diff;
            std::cout << "We should reach this, but we don't.\n";
        }
    }
    return MNE;
}



int main()
{
    int w = 1;
    int h = 1;
    array2d<uint64> a;
    if (!a.init(w,h)) return 1;
    a.fill(0);
    array2d<uint64> b;
    if (!b.init(w,h)) return 1;
    b.fill(0);
    a[0] = 0ull;
    b[0] = 1;
    std::cout << a[0] << " " << b[0] << "\n";
    auto e = computeErrors(a, b);
    std::cout << "MNE: " << e << "\n";

    return 0;
}

If I compile it with /O1, or /O2, or /Ox; with /Ot and /Ob2, then diff is always 0, when it shouldn't be. If I compile without /Ot or without /Ob2 everything works as intended. Is there anything ill-formed in this code? I have attached the whole thing here: http://coliru.stacked-crooked.com/a/245f23f05df39418 . If I change the array's [] operator to return const T& rather than T, however, everything works fine. Is this a compiler bug? Or is it my bad returning T rather than const T& in the operator[] (I am returning T since I read somewhere that passing smaller PODs by value is faster, in my case I have some arrays with uint32 where speed is very important). I am currently using Visual C++ 2017.

EDIT: As per user4581301's advice I added the whole code here too.

EDIT2: This is my _MSC_FULL_VER: 191125547.

The report was submitted (I assume by @lightxbulb) to Visual Studio Developer Community on Feb 28, 2018.

On May 8, 2018, it was reported (same link) that the issue was resolved in the most recent Visual Studio Release, which was 2017 15.7 (as per the information in the post header).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM