First I'll start by saying the question is maybe wrong, as I am not sure what is the issue with the following code.
#include <array>
#include <cstdint>
#include <iostream>
template <typename T>
struct PixelRGB {
T r {};
T g {};
T b {};
};
using PixelRGBui8 = PixelRGB<uint8_t>;
template <typename Pixel_T>
class FrameRowView {
public:
FrameRowView(const uint32_t& width)
: m_width { width }
{
}
const uint32_t& m_width;
};
double bar(auto& view)
{
std::array<PixelRGBui8, 128> arrayA = {};
std::cout << "width: " << view.m_width << " " << arrayA.data() << "\n";
return 42.0;
}
void foo()
{
static constexpr auto Width = 16;
auto frameRowPrev = FrameRowView<PixelRGBui8> { Width };
auto val = bar(frameRowPrev);
std::cout << "frameRowPrev: " << frameRowPrev.m_width << "\n";
}
int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[])
{
foo();
return EXIT_SUCCESS;
}
and on compiler explorer
Now the expected output is width: 16.
Clang in -O0 and -O3 output the right answer but in -O0 ASAN gives me an error about stack-use-after-scope.
==1==ERROR: AddressSanitizer: stack-use-after-scope on address 0x7fe67e200040 at pc 0x55c0732b8ac1 bp 0x7fff5d95d590 sp 0x7fff5d95d588
READ of size 4 at 0x7fe67e200040 thread T0
#0 0x55c0732b8ac0 in double bar<FrameRowView<PixelRGB<unsigned char>>>(FrameRowView<PixelRGB<unsigned char>>&) /app/example.cpp:27:34 #1 0x55c0732b8621 in foo() /app/example.cpp:36:14 #2 0x55c0732b874a in main /app/example.cpp:43:3 #3 0x7fe6807190b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x240b2) (BuildId: 9fdb74e7b217d06c93172a8243f8547f947ee6d1) #4 0x55c0731e137d in _start (/app/output.s+0x2137d)Address 0x7fe67e200040 is located in stack of thread T0 at offset 64 in frame #0 0x55c0732b84ff in foo() /app/example.cpp:32
This frame has 2 object(s):
[32, 40) 'frameRowPrev' (line 35) [64, 68) 'ref.tmp' (line 35) <== Memory access at offset 64 is inside this variableHINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork (longjmp and C++ exceptions are supported)
MSVC in /O0 output the right answer but in /O2 output garbage. Actually if you play with the size of the array named arrayA in the function bar and set it to 1 the output is actually good.
I am tempted to say it is a false positive on ASAN and a bug from MSVC? But it could be my bug too.
Does anybody know the answer to this riddle?