I was refactoring some code and it started segfaulting. After some debugging, I realized a made a basic type error (inserting a vector of values into a value of pointers). However, I am very surprised that this was able to compile in the first place as it seems to violate basic type rules.
Here's a minimal example:
struct SomeStruct
{
int foo;
};
etl::vector<SomeStruct, 4> myStructs{{1}, {2}, {3}, {4}};
etl::vector<SomeStruct *, 4> structPointers;
structPointers.insert(structPointers.end(), myStructs.begin(), myStructs.end());
printf("structPointers[0] = %p\n", structPointers[0]);
This compiles, and on my 64-bit desktop prints
structPointers[0] = 0000000200000001
If I change it to instead use std::vector, we get the expected compile error:
C:/msys64/ucrt64/include/c++/15.2.0/bits/stl_algobase.h:407:16: error: cannot convert 'SomeStruct' to 'SomeStruct*' in assignment
407 | *__out = *__in;
| ~~~~~~~^~~~~~~
It looks like the issue here is that the underlying insert implementation (etl::pvoidvector::insert) erases the type information of the source iterators and just treats them as void ** (rather than, in this case, SomeStruct *). This leads to it basically memcpy-ing the SomeStruct entries into the destination vector.
I think the best fix here would be to add some checks in the upper level class, etl::ivector<T*>, that the iterators passed to insert() (and probably other functions that accept iterators) are compatible with the type of the vector's elements.
I was refactoring some code and it started segfaulting. After some debugging, I realized a made a basic type error (inserting a vector of values into a value of pointers). However, I am very surprised that this was able to compile in the first place as it seems to violate basic type rules.
Here's a minimal example:
This compiles, and on my 64-bit desktop prints
If I change it to instead use std::vector, we get the expected compile error:
It looks like the issue here is that the underlying insert implementation (
etl::pvoidvector::insert) erases the type information of the source iterators and just treats them asvoid **(rather than, in this case, SomeStruct *). This leads to it basically memcpy-ing the SomeStruct entries into the destination vector.I think the best fix here would be to add some checks in the upper level class,
etl::ivector<T*>, that the iterators passed toinsert()(and probably other functions that accept iterators) are compatible with the type of the vector's elements.