I would like to know if I am in an atexit() handler. I'm looking for the moral equivalent of std::uncaught_exceptions() for exit() calls.
I want to do this so I can have the destructors in my static objects behave one way when my main() function returns, and another way when exit() is called.
I could add a call to atexit() that sets a bool I inspect, but that runs into ordering issues. For example, this:
#include <iostream>
#include <stdlib.h>
struct Setter {
static void set_in_at_exit() { in_at_exit = true; std::cout << "setting\n";}
Setter() { std::cout << "constructor\n"; atexit(set_in_at_exit); }
static bool in_at_exit;
};
bool Setter::in_at_exit = false;
struct A {
A() { static Setter s; }
~A() { if (Setter::in_at_exit) {
std::cout << "in at exit\n";
}
std::cout << "My destructor\n"; }
};
A a;
int main()
{
return 0;
}
produces:
constructor
My destructor
setting
Which is not what I want. The destructor doesn't know it is in an exit handler.
[basic.start.main]
A return statement (8.6.3) in main has the effect of leaving the main function (destroying any objects with
automatic storage duration) and calling std::exit with the return value as the argument. If control flows off the end of the compound-statement of main, the effect is equivalent to a return with operand 0
So no, you cannot distinguish between the two situations unless you somehow instrument all explicit calls to exit or all return statements and the last line before the closing brace in main.
Related
Take an example:
int foo(){
if(<THIS IS THE SECOND TIME YOU CALL FOO>) // I need some indicator like this
return 1;
else
return foo();
}
Essentially, I'm looking for an indicator that tells me "hey this is the second time that you have called foo". (I'm trying to avoid using static variables or changing foo function itself, just for sake of this exercise.)
I'm guessing if there's any variable related to the function's current stack frame (or maybe the caller stack frame) which I can exploit and use?
You can leverage a thread_local counter, along with a RAII object to increment a counter at some point in your function and decrement it when the thread leaves the function.
By creating an instance of this object with automatic storage duration (as a local variable) near the top of the function you can know how many times the current thread has called the function without returning yet.
By including an auto template argument, you can also provide the function as the template argument to allow the class to be reused in different functions.
Live example :
template<auto>
class stack_count
{
public:
stack_count() {
counter()++;
}
~stack_count() {
counter()--;
}
stack_count(const stack_count&) = delete;
void operator=(const stack_count&) = delete;
int get() const {
return counter();
}
private:
static int & counter() {
thread_local int counter = 0;
return counter;
}
};
#include <iostream>
int foo()
{
stack_count<&foo> counter;
std::cout << counter.get() << '\n';
if(counter.get() == 2) {
return 42;
}
else {
return foo();
}
}
int main()
{
const auto result = foo();
std::cout << "foo() : " << result << '\n';
}
I'm assuming you want to detect when foo has been called recursively, not when it's been called twice.
And I am guessing you're trying to avoid changing the function signature of foo, but can do whatever you want with the implementation. If that's the case, an inner "implementation" (impl) function that lets you pass the recursion count. The original function foo just calls the implementation function with a seed value:
int fooImpl(int count) {
if (count == 2) {
// this is the second time you've called foo
return 0; // return any value you want
} else {
return fooImpl(count+1);
}
}
int foo(){
return fooImpl(1);
}
And if you don't want to escape the bounds of the function, then use an internal lambda:
int foo() {
std::function<int(int)> fn;
fn = [&fn](int count)->int {
if (count == 2) {
// this is the second time you've called foo
return 0; // return any value you want
}
else {
return fn(count + 1);
}
};
return fn(1);
}
English is not my native language,so please forgive me for my grammar problems.
When I run my program, I find that class constructors are called when defining objects and explicitly calling constructors。After calling the constructor and after leaving the scope, the destructor is called twice。
#include<iostream>
class test {
private:
int a;
int b;
int c;
public:
test(int first = 0, int second = 0, int third=0 );
void show();
~test();
};
void test::show() {
std::cout << this->a<<"\n";
}
test::test(int first , int second , int third ) {
this->a = first;
this->b = second;
this->c = third;
std::cout << "Construct\n";
}
test::~test() { std::cout << "destruct\n"; }
extern test myclassone;
#include <iostream>
#include "myhead.h"
test myclassone;
int main()
{
std::cout << "begain\n";
{
std::cout << "mid\n";
myclassone = test(1,1,1);
std::cout << "mid\n";
myclassone.show();
}
std::cout << "end\n";
}
The output of this program is
Construct
begain
mid
Construct
destruct
mid
1
end
destruct
In my expectation, constructors and destructors will only be called once. But what's puzzling is that according to the output, they were called twice.
I've googled this question, and many of the answers have not explained why the constructor is called when the object is defined, and why the destructor is called immediately after the constructor is called
Your program runs as follows:
The constructor is called for the global object test myclassone;.
main() is called.
begain and mid are printed.
The constructor is called for the temporal object test(1,1,1).
The temporal object is assigned to the global object.
The destructor is called for the temporal object test(1,1,1).
mid is printed.
myclassone.show() is called.
end is printed.
Return from main().
The destructor is called for the global object test myclassone;
Therefore the constructor and destuctor are called once for each objects and called twice in total.
The following code work and prints out Dead. How does the call to callback_fn not cause a crash since destructor is obviously called?
#include <iostream>
#include <memory>
#include <functional>
class A {
private:
std::string message = "Alive";
public:
~A() { message = "Dead"; }
auto get_callback() { return [this](){ callback(); }; }
private:
void callback() const { std::cout << message << std::endl; }
};
int main()
{
std::function<void()> callback_fn;
{
A a;
callback_fn = a.get_callback();
}
callback_fn();
}
Since this is captured by value:
How does the member function call work after object destruction?
Why isn't the memory of message being freed at a destruction?
If I write main like this, I get no output (which I suspect to be undefined behaviour). I would expect the same behaviour as the code abve.
int main()
{
auto a = std::make_unique<A>();
auto callback_fn = a->get_callback();
a.reset();
callback_fn();
}
tl;dr - this code does what it does by pure accident
You are invoking undefined behaviour here. Anything could happen when you use object after its destruction. (Un)Luckily for you it works and prints your variable. But it might as well crash the program or summon demons straight from hell as it is invalid C++ code.
#include<iostream>
using namespace std;
class Test
{
public:
static int Retr(); // Static member function
//~Test(); // Test destructor
Test(); // Default constructor
private:
static int count; // Static member variable
int i;
};
int Test::count = 0; // Initialization
int main()
{
Test obj;
cout << Test::Retr() << endl;
// The result should be 1 but prints two
return 0;
}
Test::Test() : i(1) { Retr(); }
int Test::Retr()
{
return ++count;
}
/*
Test::~Test()
{
count--;
}
*/
I'm practising about usage of static member function and variable. I have a static member function that counts and returns how many objects are constructed. It should show 1 for this example but it shows 2. I don't understand why it happens. However, the destructor decreases the counter end of scope for every constructed objects. Doesn't it? So, the result using with destructor should be 0. But, I can't get the expected results. Could someone explain?
Edited what about not working of destructor ? Solved
#include<iostream>
using namespace std;
class Test
{
public:
static int Retr(); // Static member function
~Test(); // Test destructor
Test(); // Default constructor
private:
static int count; // Static member variable
int i;
};
int Test::count = 0; // Initialization
int main()
{
Test obj[2];
cout << Test::Retr() << endl;
// The result should be 0 because of destructor but prints 2
return 0;
}
Test::Test() : i(1) { ++count; }
int Test::Retr()
{
return count;
}
Test::~Test()
{
--count;
cout << Test::Retr() << endl;
}
Test::Test() : i(1) { Retr(); }
When you have created an object, It also calls retr() function. Thats increments count; And again you call retr() to show..
Your destructor is working.Call Test::Retr() to check count after destruction.
Test::~Test()
{
--count;
cout << Test::Retr() << endl;
}
First things first, you need to understand what is a static member function.
Static members of a class are not associated with the objects of the class: they are independent objects with static storage duration or regular functions defined in namespace scope, only once in the program.
So your entire program will only have one instance of count (Which is initialized to 0)
Let us look at the code in the main function, you're creating an object of the class Test. Hence the constructor gets called, which inturn calls the static int Retr() function. Hence count is now 1. Now,
cout << Test::Retr() << endl;
Calls Retr() again, hence it increments count and returns the value. Hence 2 is returned.
As far as the destructor is concerned, it is not called before the cout. It will be called only when obj goes out of scope, which will happen only when the main function is completed.
When you are creating
Test obj;
It calls the constructor and increments 1
and again you are calling
Test::retr()
It also increments 1.
If you want to check the behavior of your class you can add additional function as
void testFunction(){
Test obj[2];
std::cout << Test::Retr() << std::endl; // count became 3
}
int main(){
testFunction();
// Obj destructed here count became 1
std::cout << Test::Retr() << std::endl;
// It will again increment and count will be 2
}
Here is my program below.
void fun1(void);
int main(int argc, char *argv[])
{
cout<<"In main"<<endl;
atexit(fun1); //atexit calls the function at the end of main
cout<<"Exit main"<<endl;
return 0;
}
void fun1(void)
{
cout<<"fun1 executed"<<endl;
}
The output is
In main
Exit main
fun1 executed
But I intend the output like this:
In main
fun1 executed
Exit main
I don't want to call "fun1" function directly or use any other functions which would call my function "fun1".
Is there any way I can acheive this this output? Any help is most welcome.
No. †
Only atexit and static object destruction happen "on their own", and both these things occur after returning from main.
And this makes sense, when you think about it: something that should occur during main should be written in main. If you need a function to be invoked at a given time, write it into your program. This is what you write the program for. main is for your program.
† Probably, with a "trick" or "hack" that'll get you fired from my team.
Here is a hack using a scope:
#include <iostream>
class call_on_destructed {
private:
void (*m_callee)();
public:
call_on_destructed(void (*callee)()): m_callee(callee) {}
~call_on_destructed() {
m_callee();
}
};
void fun() {
std::cout << "fun\n";
}
int main() {
{
call_on_destructed c(&fun);
std::cout << "In main" << std::endl;
}
std::cout<<"Exit main"<<std::endl;
}
Outputs:
In main
fun
Exit main
The scope end causes the class destructor to be invoked, which in turn calls the fun function, registered within the class.
Do you want something like:
void fun1(void)
{
std::cout << "fun1 executed" << std::endl;
}
void call(void f())
{
f();
}
int main(int argc, char *argv[])
{
std::cout << "In main" << std::endl;
call(fun1); //call calls the given function directly
std::cout << "Exit main" << std::endl;
return 0;
}
Clearly, if you want to have your function executed, something is going to call it! That is, calling your function without calling your function won't work. atexit() is also just calling your function: you register what's being called eventually.
From the sounds of it, your assignment asks to pass off a function object off and have that facility call your function. For example, you could use a function caller:
template <typename F>
void caller(F f) {
f();
}
int main() {
std::cout << "entering main\n";
caller(fun1);
std::cout << "exiting main()\n";
}
Clearly, caller() does call fun1 although without mentioning that name.