#Why does this not crash due to read after out of scope?
62 messages · Page 1 of 1 (latest)
When your question is answered use !solved to mark the question as resolved.
Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.
what do you mean? list1 = list2 is copy assignment
there is no out of scope usage here
initializer list is the equivalent of pair<Double*, Double*>
this is like using string_view and reading out of scope
but it doesn't break
why
because undefined behavior is undefined
so it may do exactly what you expect
does asan catch this
;compile cpp -includeinitializer_list -includeiostream -fsanitize=address
=================================================================
==1==ERROR: AddressSanitizer: stack-use-after-scope on address 0x7fd38b900020 at pc 0x000000401493 bp 0x7ffcd65384d0 sp 0x7ffcd65384c8
READ of size 4 at 0x7fd38b900020 thread T0
#0 0x401492 in main /app/example.cpp:15
#1 0x7fd38d829d8f (/lib/x86_64-linux-gnu/libc.so.6+0x29d8f) (BuildId: a43bfc8428df6623cd498c9c0caeb91aec9be4f9)
#2 0x7fd38d829e3f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e3f) (BuildId: a43bfc8428df6623cd498c9c0caeb91aec9be4f9)
#3 0x401114 in _start (/app/output.s+0x401114) (BuildId: ee91c2ef5e1ab12573cbd53123e44633d37baeec)
Address 0x7fd38b900020 is located in stack of thread T0 at offset 32 in frame
#0 0x4011e5 in main /app/example.cpp:6
This frame has 3 object(s):
[32, 40) '<unknown>' <== Memory access at offset 32 is inside this variable
[64, 80) 'list1' (line 7)
[96, 112) 'list2' (line 10)
HINT: this may be a false positive if your program uses s
yeah
I guess I have some cppreference reading to do
hahahaha, busteeeeeeeeed
hell yeah
the reason it's UB is because std::initializer_list acts like a span
so I am not going crazy, this works exactly as expected
list2 uses a local fixed length array of const Demo
and it grabs begin and end
when you create an initializer_list object here it's implicitly creating an array for the same lifetime as the initializer_list object
see, the cppreference docs do not even show this constructor...
so let me pop open the debugger
and inspect the type
it doesn't show any constructors because the type is magical
there isn't any way of creating this type in standard C++
pffff, haha, that's like, the most useless thing ever in cppreference
yes we know, compiler support bla bla
if it were to show a constructor taking two T*s or something similar, that would be misleading because there isn't guaranteed to actually be such a constructor
instead it describes it in the notes
private constructor
it has a default constructor, a user-made constructor private with iter and count
and here, apparently, the compiler decided to auto generate rule of 3
possibly even rule of 5
in my opinion, the copy constructor and the assignment operator of this thing need to be declared as deleted
why?
otherwise holy shit it's just too easy to do read after out of scope
how would you pass an initializer_list into another function with copying deleted?
const initializer_list<T>&
or something like that
this thing acts like a view that cannot modify the underlying const array anyways
this is just something that C++ has
it's easy to smuggle out references to dead objects in general
it should be far far harder to do this, the only warnings we get and cppcon talks we get are about string_view, and ranges library
this thing is here since C++11
if you have no clue how exactly initializer_list behaves, you might think it is a literal std::array, deep copying all the things
and, pay with YOUR LIFE
for that bug
anyways
!solved
Thank you and let us know if you have any more questions!
This thread is now set to auto-hide after an hour of inactivity
confirmed, rule of 5, even the copy constructor is noexcept
just, WILD
references and pointers existed in C++98 and could be used to create the same problems with referencing dead objects
yeah, I don't see what's so crazy about it