I'm getting strange behavior bounds checking a member std::array with mingw (gcc 4.7.0) with the following code
#include <iostream>
#include <array>
class testClass
{
std::array<int, 2> testArray;
public:
testClass();
void func() const;
};
testClass::testClass() : testArray({{1, 2}})
{
}
void testClass::func() const
{
for (int i = 0; i < 2; ++i)
std::cout << testArray.at(i) << '\n' << testArray[i] << '\n';
}
int main()
{
testClass test;
test.func();
}
Output is
0
1
0
2
The error seems to be related to optimization, as it only crops up when compiled with -O
, I tried the individual flags enabled by -O
but couldn't narrow it down any further. Making the function non-const also fixes the issue. Could this be a bug or am I missing something?
*edit
Narrowed it down, looks like a bug in the const
version of .at()
#include <iostream>
#include <array>
int main()
{
std::array<int, 2> const testArray = {1, 2};
for (int i = 0; i < 2; ++i)
std::cout << testArray.at(i) << '\n' << testArray[i] << '\n';
}
Same output as above compiled with -std=c++11 -O
using mingw 4.7.0 on Windows Xp sp3 and Windows 7 sp1.
*edit 2
Same output again
#include <iostream>
#include <array>
int main()
{
typedef std::array<int, 2> Tarray;
Tarray test = {1, 2};
for (int i = 0; i < 2; ++i)
std::cout << const_cast<Tarray const*>(&test)->at(i) << '\n' << test.at(i) << '\n';
}
This is part of array header
#ifdef __EXCEPTIONS
constexpr const_reference
at(size_type __n) const
{
return __n < _Nm ?
_M_instance[__n] : throw out_of_range(__N("array::at"));
}
#else
const_reference
at(size_type __n) const
{
if (__n >= _Nm)
std::__throw_out_of_range(__N("array::at"));
return _M_instance[__n];
}
#endif
Undef __EXCEPTIONS in main file(or change #ifdef
to #ifndef
in array) leads to correct output. I don't know, this is right solution or not, but it works.
UPD: I change the code in my array's header to
#ifdef __EXCEPTIONS
constexpr const_reference
at(size_type __n) const
{
return __n < _Nm ?
_M_instance[__n] : (throw out_of_range(__N("array::at"))),
_M_instance[__n];
/*return __n < _Nm ?
_M_instance[__n] : throw out_of_range(__N("array::at"));*/
}
#else
const_reference
at(size_type __n) const
{
if (__n >= _Nm)
std::__throw_out_of_range(__N("array::at"));
return _M_instance[__n];
}
#endif
Now everything is working correctly
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With