I found a very strange problem with this pointer in c++11's lambda.
#include <string>
#include <iostream>
using namespace std;
#include <boost/signals2.hpp>
boost::signals2::signal<void()> sig;
struct out {
void print_something() {
cout << "something" << endl;
}
out() {
auto start = [&] {
cout << "this in start: " << this << endl;
this->print_something();
};
cout << "this in constructor: " << this << endl;
// sig.connect(start);
sig.connect([&] {
cout << "this in signal: " << this << endl;
start();
});
this->print_something();
}
};
int main() {
out o;
sig();
}
The code prints three this(s) pointer at different location. I was expecting that all the three this pointer should be the same value, but they are not. Here's the output:
this in constructor: 00F3FABB
something
this in signal: 00F3FABB
this in start: 00F3FB00
something
Question 1: Why is this in start has different value? How to correct it?
Question 2: Since the this in start is a different pointer, it shouldn't be able to call print_something(). I would expect a crash on this but it works fine. Why?
You capture start by reference, but the variable start and the contained lambda function get destroyed at the end of out().
Later the signal handler tries to call start(), but the lambda function doesn't exist anymore. Maybe the memory where its this was stored was overwritten in the mean time, causing unexpected output.
The call to print_something() doesn't crash despite of the invalid this because the function doesn't actually try to use this. The printing in the function is independent of this and the lookup of print_somethings address can happen at compile time so that calling the function doesn't access this at runtime.
Related
Lets say Typed Actor A needs to command Typed Actor B to do something. Actor A also needs to know if the command ran succesfully or not but does not want to block operation until this response arrives. My current working theory is that this is best satisfied with Requests. More specifically request(...).then
There is a nice example called "request.cpp" that I have been playing with. My challenge is that I don't really need actor B to return any data. I just need to know if the command was successful or not and if not what error was thrown.
So my question is two fold: 1) Am I correct in thinking that request(...).then is the correct mechanism to do what I want and 2) if so then can a request handle a response that has no data?
This is what I'm trying:
#include <chrono>
#include <cstdint>
#include <iostream>
#include <vector>
#include "caf/all.hpp"
using std::endl;
using std::vector;
using std::chrono::seconds;
using namespace caf;
using cell
= typed_actor<result<void>(get_atom, int32_t)>;
struct cell_state {
static constexpr inline const char* name = "cell";
cell::pointer self;
cell_state(cell::pointer ptr) : self(ptr) {}
cell_state(const cell_state&) = delete;
cell_state& operator=(const cell_state&) = delete;
cell::behavior_type make_behavior() {
return {
[=](get_atom, int32_t input) -> result<void> {
if (input != 5) { // Simulate command successful or not
return; // If successful, then return;
}
else {
return sec::unexpected_message; // If not then return error.
}
},
};
}
};
using cell_impl = cell::stateful_impl<cell_state>;
void multiplexed_testee(event_based_actor* self, vector<cell> cells) {
for (cell& x : cells) {
aout(self) << "cell #" << x.id() << " calling" << endl;
self->request(x, seconds(1), get_atom_v, static_cast<int32_t>(x.id()))
.then(
[=](void) {
aout(self) << "cell #" << x.id() << " -> " << "success" << endl;
},
[=](error& err) {
aout(self) << "cell #" << x.id() << " -> " << to_string(err) << endl;
});
}
}
void caf_main(actor_system& system) {
vector<cell> cells;
for (int32_t i = 0; i < 5; ++i)
cells.emplace_back(system.spawn<cell_impl>());
scoped_actor self{ system };
auto x2 = self->spawn(multiplexed_testee, cells);
self->wait_for(x2);
}
CAF_MAIN()
When I compile, I get an error on the empty return statement saying "return-statement with no value, in function returning caf::result<void>. Is there a better way to do this?
My backup plan is to change my command definition to just return a standard error and return sec::none if the operation was successful. But I'm afraid that approach violates the spirit of the whole optional-second-parameter for error conditions. How well am I thinking about all this?
Is there a better way to do this?
You had the right idea. The result<void> expects either an error or a 'void' value. Since void{} isn't a thing in C++, you can do return caf::unit; to tell result<void> to construct an "empty" result. On the receiver's side, you already did the right thing: then with a lambda taking no arguments.
Minor point:
[=](void) { ... }
This is a C-ism from the early days where the compiler allowed you to do silly things. Just drop the void, it serves no purpose. :)
I‘ve been trying to understand smart pointers, and as I understood, smart pointer will destroy themselves once they are not reachable through the code.
For this reason I was trying to implement a demonstration for this behavior:
#include<iostream>
#include<memory>
using namespace std;
void shared(){
cout<<"Shared Pointer:"<<endl;
shared_ptr<int> number = make_shared<int>(50);
cout<<*number<<endl;
cout<<number<<endl;
}
int main(){
int address;
shared();
cout<<"please enter the targeted address:"<<endl;
cin>>address;
int *pointer = (int *) address;
cout<<"we found this number: "<<*pointer<<endl;
}
output:
Shared Pointer:
50
0xf28c30
please enter the targeted address:
15895600 // I just converted the hexdecimal above to decimal number.
we found this number: 50
So I‘m able to retrieve the value 50 from outside the function shared(), by manually entering its address in the console.
Isn‘t supposed to be null or random number? If this is normal then how smartpointers are made to avoid memory leaks!?
P.S: doing the same test using a normal pointer will produce the same results unless we add delete pointer; (which is the expected behavior)
I appreciate any idea about this specific behavior.
To make sure that the memory was deleted it is better to test the smart pointers with a class
class Greeting {
public:
Greeting()
{
std::cout << "Hello" << std::endl;
}
~Greeting()
{
std::cout << "Bye" << std::endl;
}
};
void shared() {
shared_ptr<Greeting> var = make_shared<Greeting>();
}
int main() {
std::cout << "Start" << std::endl;
shared();
std::cout << "End" << std::endl;
}
You will get the following output:
Start //Start of the main
Hello // When creating the object (the resource)
Bye // **When destructing the object (the resource)**
End //End the main
I've read the basics of move semantics and I did a couple of tests.
Case #1:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
string st = "hello";
vector<string> vec;
vec.push_back(st);
cout << st;
cin.get();
}
In this case, the program will not print anything because "hello" has been moved to vector[0].
Case #2:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int num=5;
vector<int> vec;
vec.push_back(num);
cout << num;
cin.get();
}
Why does the program print "5"? I thought num would be 0 or something undefined.
Case #1 should print "hello". If not then your compiler has bug and you should upgrade to a newer version or complain to who ever wrote it.
Case #2 correctly prints "5".
However, if you changed line 10 in case 2 from:
vec.push_back(st);
to:
vec.push_back(std::move(st));
you will get what you expected, a print to console of "" because vector "stole" the value in st.
int is a fundamental type in c++ and trying to "steal" from an int variable doesn't realy work since it does't own any resource.
std::string is a resource owner. It "owns" a char array (this isn't always true, but for simplicity we will pretend it is).
So when we pass std::move(st) to push_back we are calling the T&& overload of push_back which does the "stealing" by calling the move constructor of std::string which releases st's handle and gives it to the newly created std::string inside vec.
But if we called push_back like this: vec.push_back(st); this will not "steal" any thing. Instead, it will call the const T& overload of push_back which just does a simple copy by calling the normal copy constructor of std::string such that we will have st set to "hello" and vec[0] set with its own version of "hello".
Try this code below to see how all this works out:
#include <iostream>
#include <vector>
using namespace std;
struct Foo
{
Foo() // default constructor
{
cout << "Foo()" << endl;
}
Foo(const Foo&) // copy constructor
{
cout << "Foo(const Foo&)" << endl;
}
Foo(Foo&&) // move constructor
{
cout << "Foo(Foo&&)" << endl;
}
Foo& operator=(const Foo&) // copy assignment operator
{
cout << "operator=(const Foo&)" << endl;
return *this;
}
Foo& operator=(Foo&&) // move assignment operator
{
cout << "operator=(Foo&&)" << endl;
return *this;
}
~Foo()
{
cout << "~Foo()" << endl;
}
};
int main()
{
Foo f; // print: Foo();
vector<Foo> vec;
vec.push_back(f); // print: Foo(const Foo&)
vec.push_back(std::move(f)); // print: Foo(Foo&&)
Foo f2; // print: Foo()
f2 = f; // print: operator=(const Foo&)
f2 = std::move(f); // print: operator=(Foo&&)
cin.get();
}
In the following piece of code, I'm retrieving a shared_ptr<A> from a function. I then dynamically cast the pointer to a deriving class and store it in a shared_ptr<B>. The original pointer is not a nullptr.
shared_ptr<B> storage = nullptr;
if (...)
{
shared_ptr<A> definition = getSharedPointer();
// Store the lambda
storage = dynamic_pointer_cast<B>(definition);
}
I would expect the dynamic_pointer_cast and storage to storage to increase the total reference count to 2. Then, when I leave the scope of the if-statement, storage's reference count should be one.
Yet, when I tried to call a method on storage, I get a EXC_BAD_ACCESS, implying I'm reading in a deleted pointer.
storage->foo(...)->bar(...);
Is my logic wrong? Is this a bug in clang (can't imagine)?
EDIT
I seem to have found the error, which has nothing to do with the pointers. The function bar() actually gave the problem. If anyone ever reads this: the above code is perfectly valid.
This example works fine:
#include <memory>
using namespace std;
struct A {
virtual ~A() {}
};
struct B : A {};
shared_ptr<A> getSharedPointer() {
return make_shared<B>();
}
#include <iostream>
int main() {
shared_ptr<B> storage = nullptr;
if (true)
{
shared_ptr<A> definition = getSharedPointer();
// Store the lambda
storage = dynamic_pointer_cast<B>(definition);
}
cout << storage.get() << endl;
}
It would seem that your shared_ptr<A> is not pointing to a B and the result of the dynamic_pointer_cast is nullptr. Maybe a debugging statement would be helpful:
if (...)
{
shared_ptr<A> definition = getSharedPointer();
cerr << "as A: " << definition.get()
<< ", as B: " << dynamic_cast<B>(definition.get()) << endl;
// Store the lambda
storage = dynamic_pointer_cast<B>(definition);
}
Can anyone tell me how to simulate and produce the bad_alloc exception in C++? In my code in some places i am using new operator which will throw the bad_alloc exception. I want to simulate this scenario and need to test the code.
Balamurugan,
I had the same doubt this afternoon, and did not see anything related here.
So I went to CPlusPlus and put the try catch inside an infinite loop, and worked. Under VS C++ 2010 Express.
Below my code:
// bad_alloc standard exception
#include <iostream>
#include <exception>
using namespace std;
int main ()
{
unsigned int count=0;
while (1)
{
count++;
try
{
int* myarray= new int[1000000];
}
catch (exception& e)
{
cout << "Standard exception: " << e.what() << endl;
cout << "\nAborting after "<< count << " loops";
return -1;
}
}
cout<<"\nNormal finishing...";
return 0;
}
In my case, it was caught after 523 loops. I would be better if i knew a setting to limit the heap to Fisical Memory, if I find I'll make you know.