Using placement new with an std::function doesn't work - c++

This code crashes at (*function)(). I'm running Visual Studio 2019 and compiling C++17 for Windows 10 x86_64. I've tested it on Linux with GCC (-std=c++17) and it works fine. I'm wondering if this is a problem with Visual Studio's C++ compiler or something that I'm not seeing.
#include <vector>
#include <array>
#include <functional>
#include <iostream>
int main() {
const size_t blockSize = sizeof(std::function<void()>);
using block = std::array<char, blockSize>;
std::vector<block> blocks;
auto lambda = [](){
std::cout << "The lambda was successfully called.\n";
};
blocks.emplace_back();
new (&blocks[0]) std::function<void()>(lambda);
blocks.emplace_back();
new (&blocks[1]) std::function<void()>(lambda);
std::function<void()> *function = (std::function<void()> *)blocks[0].data();
(*function)();
return 0;
}
The error is a read access violation in the std::function internals.

When you append an element to a std::vector and that element would make the vector's size greater than its capacity the vector has to allocate new storage and copy/move all of its elements to the new space. While you've constructed complex std::function objects in the char arrays held in your vector, the vector doesn't know that. The underlying bytes that make up the std::function object will get copied to the vector's new storage, but the std::function's copy/move constructor won't get called.
The best solution would be to just use a std::vector<std::function<void()>> directly. If you have to use a vector of blocks of raw storage for some reason then you'll need to pre-allocate space before you start inserting elements. i.e.
int main() {
const size_t blockSize = sizeof(std::function<void()>);
using block = std::array<char, blockSize>;
std::vector<block> blocks;
auto lambda = [](){
std::cout << "The lambda was successfully called.\n";
};
blocks.reserve(2); // pre-allocate space for 2 blocks
blocks.emplace_back();
new (&blocks[0]) std::function<void()>(lambda);
blocks.emplace_back();
new (&blocks[1]) std::function<void()>(lambda);
std::function<void()> *function = (std::function<void()> *)blocks[0].data();
(*function)();
return 0;
}
Live Demo
Alternatively you could use a different data structure such as std::list that maintains stable addresses when elements are added or removed.

Related

How to represent existing data as std::vector

I have to pass existing data (unsigned char memory area with known size) to the library function expecting const std::vector<std::byte>& . Is there any way to "fool" the library function to believe that it received a vector while operating on existing data?
I have data from the old legacy as a pointer and size, not as a std::vector. Legacy C code allocates memory by malloc() and provides pointer and size. Please do not suggest touching the legacy code - by the end of the phrase I'll cease to be an employee of the company.
I don't want to create temporary vector and copy data because memory throughtput is huge (> 5GB/sec).
Placement new creates vector - but with the first bytes used for the vector data itself. I cannot use few bytes before the memory area - legacy code didn't expect that (see above - memory area is allocated by malloc()).
Changing third party library is out of question. It expects const std::vectorstd::byte& - not span iterators etc.
It looks that I have no way but to go with temporary vector but maybe there are other ideas... I wouldn't care but it is about intensive video processing and there will be a lot of data to copy for nothing.
Is there any way to "fool" the library function to believe that it received a vector while operating on existing data?
No.
The potential options are:
Put the data in a vector in the first place.
Or change the function expecting a vector to not expect a vector.
Or create a vector and copy the data.
If 1. and 2. are not valid options for you, that leaves you with 3. whether you want it or not.
As the top answer mentions, this is impossible to do in standard C++. And you should not try to do it.
If you can tolerate only using libstdc++ and getting potentially stuck with a specific standard library version, it looks like you can do it. Again, you should not do this. I'm only writing this answer as it seems to be possible without UB in this specific circumstance.
It appears that the current version of libstdc++ exposes their vectors' important members as protected: https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/stl_vector.h#L422
All you need to do is inherit from std::vector (it's not forbidden), write your own constructor for setting these protected members, and write a destructor to reset the members so that the actual vector destructor does not delete your memory.
#include <vector>
#include <cstddef>
template <class T>
struct dont_use_me_in_prod : std::vector<T>
{
dont_use_me_in_prod(T* data, size_t n) {
this->_M_impl._M_start = data;
this->_M_impl._M_finish = data + n;
this->_M_impl._M_end_of_storage = this->_M_impl._M_finish;
}
~dont_use_me_in_prod() {
this->_M_impl._M_start = nullptr;
this->_M_impl._M_finish = nullptr;
this->_M_impl._M_end_of_storage = nullptr;
}
};
void innocent_function(const std::vector<int>& v);
void please_dont_do_this_in_prod(int* vals, int n) {
dont_use_me_in_prod evil_vector(vals, n);
innocent_function(evil_vector);
}
Note that this is not compiler, but standard library dependent, meaning that it'll work with clang as well as long as you use libstdc++ with it. But this is not conforming, so you gotta fix innocent_function somehow soon:
https://godbolt.org/z/Tfcn7rdKq
The problem is std::vector is not a reference class like std::string_view or std::span. std::vector owns the managed memory. It allocates the memory and releases the owned memory. It is not designed to acquire the external buffer and release the managed buffer.
What you can do is a very dirty hack. You can create new structure with exactly the same layout as a std::vector, assign the data and size fields with what you get from external lib, and then pass this struct as a std::vector const& using reinterpret_cast. It can work as your library does not modify the vector (I assume they do not perform const_cast on std::vector const&).
The drawback is that code is unmaintainable. The next STL update can cause application crash, if the layout of the std::vector is changed.
Following is a pseudo code
struct FakeVector
{
std::byte* Data;
std::size Size;
std::size Capacity;
};
void onNewData(std::byte* ptr, size_t size)
{
auto vectorRef = FakeVector{ptr, size, size};
doSomething(*reinterpret_cast<std::vector<std::byte>*>(&vectorRef));
}
Well, I've found the way working for me. I must admit that it is not fully standard compliant because casting of vector results in undefined behavior but for the foreseeable future I wouldn't expect this to fail. Idea is to use my own Allocator for the vector that accepts the buffer from the legacy code and works on it. The problem is that std::vector<std::byte> calls default initialization on resize() that zeroes the buffer. If there is a way to disable that - it would be a perfect solution but I have not found... So here the ugly cast comes - from the std::vector<InnerType> where InnerType is nothing but std::byte with default constructor disabled to the std::vector<std::byte> that library expects. Working code is shown at https://godbolt.org/z/7jME79EE9 , also here:
#include <cstdlib>
#include <iostream>
#include <vector>
#include <cstddef>
struct InnerType {
std::byte value;
InnerType() {}
InnerType(std::byte v) : value(v) {}
};
static_assert(sizeof(InnerType) == sizeof(std::byte));
template <class T> class AllocatorExternalBufferT {
T* const _buffer;
const size_t _size;
public:
typedef T value_type;
constexpr AllocatorExternalBufferT() = delete;
constexpr AllocatorExternalBufferT(T* buf, size_t size) : _buffer(buf), _size(size) {}
[[nodiscard]] T* allocate(std::size_t n) {
if (n > _size / sizeof(T)) {
throw std::bad_array_new_length();
}
return _buffer;
}
void deallocate(T*, std::size_t) noexcept {}
};
template <class T, class U> bool operator==(const AllocatorExternalBufferT <T>&, const AllocatorExternalBufferT <U>&) { return true; }
template <class T, class U> bool operator!=(const AllocatorExternalBufferT <T>&, const AllocatorExternalBufferT <U>&) { return false; }
typedef std::vector<InnerType, AllocatorExternalBufferT<InnerType>> BufferDataVector;
typedef std::vector<std::byte, AllocatorExternalBufferT<std::byte>> InterfaceVector;
static void report(const InterfaceVector& vec) {
std::cout << "size=" << vec.size() << " capacity=" << vec.capacity() << " ";
for(const auto& el : vec) {
std::cout << static_cast<int>(el) << " ";
}
std::cout << "\n";
}
int main() {
InnerType buffer4allocator[16] ;
BufferDataVector v((AllocatorExternalBufferT<InnerType>(buffer4allocator, sizeof(buffer4allocator)))); // double parenthesis here for "most vexing parse" nonsense
v.resize(sizeof(buffer4allocator));
std::cout << "memory area kept intact after resizing vector:\n";
report(*reinterpret_cast<InterfaceVector*>(&v));
}
Yes you can do this. Not in a nice safe way but it's certainly possible.
All you need to do is create a fake std::vector that has the same ABI (memory layout) as std::vector. Then set it's internal pointer to point to your data and reinterpet_cast your fake vector back to a std::vector.
I wouldn't recommend it unless you really need to do it because any time your compiler changes its std::vector ABI (field layout basically) it will break. Though to be fair that is very unlikely to happen these days.

How to create a vector around a buffer?

I have a code which is similar to the following:
myLibFunc(std::vector<char > &data)
{
// dosomthing with data
}
myFunc(char *buffer,int bufferSize)
{
std::vector<char > mydata(buffer,buffer+bufferSize);
myLibFunc(mydata);
}
The code works, but the vector allocates memory for itself and not using a memory that is already available.
How can I change the code in such a way that the vector uses the memory that already available and not allocating an extra memory?
Note that I can not change the signature of functions.
Update
I have two functions:
In one of them, I receive a buffer and I need to manipulate the memory and pass it to the next function as a vector. The function that I am trying to implement is part of an interface so I can not change it. Another function is a library that I need to call, so I can not change the signature of functions.
The problem is that the above code allocates new memory and copies the data from the buffer to it which is not optimal.
std::vector is designed to exclusively own the data it holds so doing the memory copy is the only safe way for std::vector to work. That leaves only unsafe hacks. If we can assume the function does not change the vector size, you can abuse std::vector. In my compiler (tested on g++4.8 and cpp.sh) std::vector is implemented as three pointers (to begin data, end used data and end alloc) therefore I can abuse the vector as:
#include <vector>
#include <iostream>
void myLibFunc( std::vector< char > & a )
{
for( char c : a )
{
std::cout << '[' << c << ']';
}
a[0] = 'B'
std::cout << '\n';
}
void myFunc(char *buffer,int bufferSize)
{
std::vector<char > mydata;
// cast to alterable pointers, cast should also keep
// mydata in scope until after the last assignment.
char ** abuser = (char**)&mydata;
// save old values and substitute new values
char *tmp0 = abuser[0];
abuser[0] = buffer;
char *tmp1 = abuser[1];
abuser[1] = buffer+bufferSize;
char *tmp2 = abuser[2];
abuser[2] = buffer+bufferSize;
myLibFunc(mydata);
// return old values to avoid crash when mydata goes out of scope.
abuser[0] = tmp0;
abuser[1] = tmp1;
abuser[2] = tmp2;
}
int main()
{
char p[] = "Hello World";
myFunc( &p[0] + 2, 5 );
std::cout << p << '\n';
return 0;
}
Note this abuse is likely to be non-portable and lead to unexplained crashes.
If you can not change the signature of your function it is not possible without the copy.
But a better way is to think about your interface. If you build myLibFunc on random access iterators, your problem is solved:
template <class CharRandomAccessIterator>
myLibFunc(CharRandomAccessIterator& begin, CharRandomAccessIterator& end )
{
// dosomthing with data
size = end - begin;
begin[xyz]; // access elements
}
myFunc(char *buffer,int bufferSize)
{
std::vector<char > mydata(buffer,buffer+bufferSize);
myLibFunc(mydata.begin(), mydata.end()); // This will work
myLibFunc(buffer, buffer+size); // This will work too
}

Avoid memory allocation with std::function and member function

This code is just for illustrating the question.
#include <functional>
struct MyCallBack {
void Fire() {
}
};
int main()
{
MyCallBack cb;
std::function<void(void)> func = std::bind(&MyCallBack::Fire, &cb);
}
Experiments with valgrind shows that the line assigning to func dynamically allocates about 24 bytes with gcc 7.1.1 on linux.
In the real code, I have a few handfuls of different structs all with a void(void) member function that gets stored in ~10 million std::function<void(void)>.
Is there any way I can avoid memory being dynamically allocated when doing std::function<void(void)> func = std::bind(&MyCallBack::Fire, &cb); ? (Or otherwise assigning these member function to a std::function)
Unfortunately, allocators for std::function has been dropped in C++17.
Now the accepted solution to avoid dynamic allocations inside std::function is to use lambdas instead of std::bind. That does work, at least in GCC - it has enough static space to store the lambda in your case, but not enough space to store the binder object.
std::function<void()> func = [&cb]{ cb.Fire(); };
// sizeof lambda is sizeof(MyCallBack*), which is small enough
As a general rule, with most implementations, and with a lambda which captures only a single pointer (or a reference), you will avoid dynamic allocations inside std::function with this technique (it is also generally better approach as other answer suggests).
Keep in mind, for that to work you need guarantee that this lambda will outlive the std::function. Obviously, it is not always possible, and sometime you have to capture state by (large) copy. If that happens, there is no way currently to eliminate dynamic allocations in functions, other than tinker with STL yourself (obviously, not recommended in general case, but could be done in some specific cases).
As an addendum to the already existent and correct answer, consider the following:
MyCallBack cb;
std::cerr << sizeof(std::bind(&MyCallBack::Fire, &cb)) << "\n";
auto a = [&] { cb.Fire(); };
std::cerr << sizeof(a);
This program prints 24 and 8 for me, with both gcc and clang. I don't exactly know what bind is doing here (my understanding is that it's a fantastically complicated beast), but as you can see, it's almost absurdly inefficient here compared to a lambda.
As it happens, std::function is guaranteed to not allocate if constructed from a function pointer, which is also one word in size. So constructing a std::function from this kind of lambda, which only needs to capture a pointer to an object and should also be one word, should in practice never allocate.
Run this little hack and it probably will print the amount of bytes you can capture without allocating memory:
#include <iostream>
#include <functional>
#include <cstring>
void h(std::function<void(void*)>&& f, void* g)
{
f(g);
}
template<size_t number_of_size_t>
void do_test()
{
size_t a[number_of_size_t];
std::memset(a, 0, sizeof(a));
a[0] = sizeof(a);
std::function<void(void*)> g = [a](void* ptr) {
if (&a != ptr)
std::cout << "malloc was called when capturing " << a[0] << " bytes." << std::endl;
else
std::cout << "No allocation took place when capturing " << a[0] << " bytes." << std::endl;
};
h(std::move(g), &g);
}
int main()
{
do_test<1>();
do_test<2>();
do_test<3>();
do_test<4>();
}
With gcc version 8.3.0 this prints
No allocation took place when capturing 8 bytes.
No allocation took place when capturing 16 bytes.
malloc was called when capturing 24 bytes.
malloc was called when capturing 32 bytes.
Many std::function implementations will avoid allocations and use space inside the function class itself rather than allocating if the callback it wraps is "small enough" and has trivial copying. However, the standard does not require this, only suggests it.
On g++, a non-trivial copy constructor on a function object, or data exceeding 16 bytes, is enough to cause it to allocate. But if your function object has no data and uses the builtin copy constructor, then std::function won't allocate.
Also, if you use a function pointer or a member function pointer, it won't allocate.
While not directly part of your question, it is part of your example.
Do not use std::bind. In virtually every case, a lambda is better: smaller, better inlining, can avoid allocations, better error messages, faster compiles, the list goes on. If you want to avoid allocations, you must also avoid bind.
I propose a custom class for your specific usage.
While it's true that you shouldn't try to re-implement existing library functionality because the library ones will be much more tested and optimized, it's also true that it applies for the general case. If you have a particular situation like in your example and the standard implementation doesn't suite your needs you can explore implementing a version tailored to your specific use case, which you can measure and tweak as necessary.
So I have created a class akin to std::function<void (void)> that works only for methods and has all the storage in place (no dynamic allocations).
I have lovingly called it Trigger (inspired by your Fire method name). Please do give it a more suited name if you want to.
// helper alias for method
// can be used in user code
template <class T>
using Trigger_method = auto (T::*)() -> void;
namespace detail
{
// Polymorphic classes needed for type erasure
struct Trigger_base
{
virtual ~Trigger_base() noexcept = default;
virtual auto placement_clone(void* buffer) const noexcept -> Trigger_base* = 0;
virtual auto call() -> void = 0;
};
template <class T>
struct Trigger_actual : Trigger_base
{
T& obj;
Trigger_method<T> method;
Trigger_actual(T& obj, Trigger_method<T> method) noexcept : obj{obj}, method{method}
{
}
auto placement_clone(void* buffer) const noexcept -> Trigger_base* override
{
return new (buffer) Trigger_actual{obj, method};
}
auto call() -> void override
{
return (obj.*method)();
}
};
// in Trigger (bellow) we need to allocate enough storage
// for any Trigger_actual template instantiation
// since all templates basically contain 2 pointers
// we assume (and test it with static_asserts)
// that all will have the same size
// we will use Trigger_actual<Trigger_test_size>
// to determine the size of all Trigger_actual templates
struct Trigger_test_size {};
}
struct Trigger
{
std::aligned_storage_t<sizeof(detail::Trigger_actual<detail::Trigger_test_size>)>
trigger_actual_storage_;
// vital. We cannot just cast `&trigger_actual_storage_` to `Trigger_base*`
// because there is no guarantee by the standard that
// the base pointer will point to the start of the derived object
// so we need to store separately the base pointer
detail::Trigger_base* base_ptr = nullptr;
template <class X>
Trigger(X& x, Trigger_method<X> method) noexcept
{
static_assert(sizeof(trigger_actual_storage_) >=
sizeof(detail::Trigger_actual<X>));
static_assert(alignof(decltype(trigger_actual_storage_)) %
alignof(detail::Trigger_actual<X>) == 0);
base_ptr = new (&trigger_actual_storage_) detail::Trigger_actual<X>{x, method};
}
Trigger(const Trigger& other) noexcept
{
if (other.base_ptr)
{
base_ptr = other.base_ptr->placement_clone(&trigger_actual_storage_);
}
}
auto operator=(const Trigger& other) noexcept -> Trigger&
{
destroy_actual();
if (other.base_ptr)
{
base_ptr = other.base_ptr->placement_clone(&trigger_actual_storage_);
}
return *this;
}
~Trigger() noexcept
{
destroy_actual();
}
auto destroy_actual() noexcept -> void
{
if (base_ptr)
{
base_ptr->~Trigger_base();
base_ptr = nullptr;
}
}
auto operator()() const
{
if (!base_ptr)
{
// deal with this situation (error or just ignore and return)
}
base_ptr->call();
}
};
Usage:
struct X
{
auto foo() -> void;
};
auto test()
{
X x;
Trigger f{x, &X::foo};
f();
}
Warning: only tested for compilation errors.
You need to thoroughly test it for correctness.
You need to profile it and see if it has a better performance than other solutions. The advantage of this is because it's in house cooked you can make tweaks to the implementation to increase performance on your specific scenarios.
As #Quuxplusone mentioned in their answer-as-a-comment, you can use inplace_function here. Include the header in your project, and then use like this:
#include "inplace_function.h"
struct big { char foo[20]; };
static stdext::inplace_function<void(), 8> inplacefunc;
static std::function<void()> stdfunc;
int main() {
static_assert(sizeof(inplacefunc) == 16);
static_assert(sizeof(stdfunc) == 32);
inplacefunc = []() {};
// fine
struct big a;
inplacefunc = [a]() {};
// test.cpp:15:24: required from here
// inplace_function.h:237:33: error: static assertion failed: inplace_function cannot be constructed from object with this (large) size
// 237 | static_assert(sizeof(C) <= Capacity,
// | ~~~~~~~~~~^~~~~~~~~~~
// inplace_function.h:237:33: note: the comparison reduces to ‘(20 <= 8)’
}

Moving elements from std::vector<T1> to std::vector<std::pair<T1,T2>>

What is the most correct and efficient way to std::move elements from a vector of a certain type (T1) into a vector of an std::pair of that same type (T1) and another type (T2)?
In other words, how should I write MoveItems()?
#include <iostream> // For std::string
#include <string> // For std::string
#include <vector> // For std::vector
#include <utility> // For std::pair
using std::vector;
using std::string;
using std::pair;
vector<string> DownloadedItems;
vector<pair<string,bool>> ActiveItems;
vector<string> Download()
{
vector<string> Items {"These","Words","Are","Usually","Downloaded"};
return Items;
}
void MoveItems()
{
for ( size_t i = 0; i < DownloadedItems.size(); ++i )
ActiveItems.push_back( std::pair<string,bool>(DownloadedItems.at(i),true) );
}
int main()
{
DownloadedItems = Download();
MoveItems();
return 0;
}
Thank you for your time and help, I truly appreciate it!
void MoveItems()
{
ActiveItems.reserve(DownloadedItems.size());
for (auto& str : DownloadedItems)
ActiveItems.emplace_back(std::move(str), true);
}
N.B.: For strings as small as the ones in your example, moving may have the same cost as copying due to SSO, or perhaps even slightly more expensive if the implementation decides to empty out the source anyway.
Some things you can do:
At the start of MoveItems(), call ActiveItems.reserve(DownloadedItems.size());. This prevents your array from resizing while you push things into it.
Instead of calling push_back call emplace_back. Here is an explanation of the advantages of doing so.
Worth noting, in this example, you can stop the copy into a new data structure by just constructing the std::pair from the start, and not copying data.

Is it possible to use custom allocation operator to create a STACK object?

Ok, if I want to create a heap object with a custom new operator, I know that I need to overload the new operator like this:
void* operator new(size_t size, int unused)
{
void* ptr = malloc(size);
//some custom code
return ptr;
}
And then, if I want to create a heap object using this overloaded operator I would do this:
SomeClass* a = new(0) SomeClass;
The question is: can I do something like this to create a stack object?
I agree with other answers that you probably don't need this but you could do it. See sample code below, just allocate the memory ahead of time and pass it into placement new. You might want to do this if you are using the array new[] form where you might do something like
void *rawMemory = operator new[](25*sizeof(std::stack));
if you had an array of stacks that you had a factory method that managed the resources or something. Either way it depends on your application and use cases. Below shows a simple example
#include <iostream>
#include <stack>
int main ( int argc, char *argv[])
{
void *rawMemory = operator new(sizeof(std::stack<unsigned int>));
std::stack<unsigned int> *s = new (rawMemory) std::stack<unsigned int>;
s->push(10);
std::cout << s->top() << std::endl;
return 0;
}
Second example using the array version, which seems more useful where you may be managing 25 different stacks and handing them to clients. Also, answering your comment. See that the container is defined in the stack definition this time, in this case I am using a vector for the container. Stack is a container but it has an underlying container that defaults to deque
#include <iostream>
#include <stack>
#include <vector>
int main ( int argc, char *argv[])
{
typedef std::stack<unsigned int,std::vector<unsigned int> > StackType;
void *rawMemory = operator new[](25*sizeof(StackType));
StackType *stacks = static_cast<StackType*> (rawMemory);
// allocate
for ( unsigned int i = 0; i < 25; ++i )
{
new (stacks+i) StackType;
}
stacks[1].push(10);
std::cout << stacks[1].top() << std::endl;
// don't forget to delete or smart resize
for ( int i = 24; i >= 0; --i )
{
StackType x;
std::swap ( x, stacks[i] );
}
return 0;
}
You can define a macro like this:
#define STACK_NEW(T) new (alloca(sizeof(T))) T
that uses placement new and alloca() to allocate a block on the stack and construct an object of type T on top of it. You can also define an array version:
#define STACK_NEW_ARRAY(T, n) new (alloca(n * sizeof(T))) T
You'd use this macro in the following ways:
int * p = STACK_NEW(int);
MyObj * q = STACK_NEW(MyObj) (my, constructor, parameters);
int * r = STACK_NEW_ARRAY(int, 42);
You'll have destruct these objects manually:
q->~MyObj();
Deleting them will have undefined behavior.
WARNING: This whole facility is very unsafe. I'd strongly recommend against having such systematically dangerous tools in your codebase. As far as I can see, there is no safe way to use it and it will cause you pain!