Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrong output for the initialization of static variables within a function #507

Closed
Redstone1024 opened this issue Oct 29, 2022 · 2 comments
Closed
Labels
bug Something isn't working

Comments

@Redstone1024
Copy link

Redstone1024 commented Oct 29, 2022

For the initialization of static variables within functions, based on comparison with assembly output and analysis, I believe that a call to __cxa_atexit should be included, otherwise the class object cannot be destructured on program exit.

The following references are used in the analysis process.

C++ Insights

Compiler Explorer

This function call is missing.

mov     edx, OFFSET FLAT:__dso_handle
mov     esi, OFFSET FLAT:_ZZ11get_examplevE4temp
mov     edi, OFFSET FLAT:_ZN14example_structD1Ev
call    __cxa_atexit

Translated with DeepL.

@andreasfertig
Copy link
Owner

Hello @Redstone1024,

thanks for reporting this. As far as I can tell, you're right. The only thing is that __cxa_atexit requires parameters. C++ Insights doesn't show destructors as they are not part of the AST. I must figure out what I want to do in this special case. Of course, if you bring me a PR, I will most likely accept that :-)

Andreas

@andreasfertig andreasfertig added the bug Something isn't working label Oct 31, 2022
@Redstone1024
Copy link
Author

Redstone1024 commented Oct 31, 2022

Thanks for the reply, also if(!__tempGuard) should it be if((__tempGuard & 0xff) == 0) ? After all, here it should ensure that the initialization is complete, not continue the logic below while other threads are initializing.

Also __tempGuard = true; doesn't seem to be correct.

Here is the test code with what I think the output is.

struct example_struct
{
	example_struct() { throw; }
	~example_struct() { }
};

example_struct& get_example()
{
	static example_struct temp;
	return temp;
}
struct example_struct
{
	inline example_struct() { throw; }
	inline ~example_struct() noexcept { }
};

example_struct& get_example()
{
	static uint64_t __tempGuard;
	alignas(example_struct) static char __temp[sizeof(example_struct)];
	if((__tempGuard & 0xff) == 0)
	{
		if(__cxa_guard_acquire(&__tempGuard))
		{
			try
			{
				new (&__temp) example_struct();
			}
			catch(...)
			{
				__cxa_guard_abort(&__tempGuard);
				throw;
			}
			__cxa_guard_release(&__tempGuard);
			__cxa_atexit(example_struct::~example_struct, &__temp, &__dso_handle);
		}
	}
	return *reinterpret_cast<example_struct*>(__temp);
}

Thanks again.

andreasfertig added a commit that referenced this issue Mar 12, 2024
Fixed #507: Improved support for static variables.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants