On Tuesday 26 August 2025 10:41:28 LIU Hao wrote:
> 在 2025-8-26 03:54, Pali Rohár 写道:
> > It was intended as a cleanup. __main is currently using atexit hooks to
> > execute c++ destructors but for dll builds this can be done in more
> > clean why by explicitly calling them at process detach event without
> > need to maintain per-dll atexit hook table and hence completely avoid
> > atexit call inclusion into every dll library.
>
> This might violate the C++ standard which requires destructors and exit
> callbacks be called in the reverse order of their completion (of a
> destructor of a static object, which may be either a local one or a global
> one with namespace scope) and registration (of an exit callback). Yes
> there's a requirement on the order of these unrelated things.
Order of destructors in which they are called is not changed. So this
should not be a problem. We are using one atexit hook for all
destructors and this hook is calling destructors in correct reverse order.
>
> > > The interface around "__main" can be entrenched in many places, and code
> > > expecting to e.g. override the entry point and just call "__main" no
> > > longer
> > > will have working C++ constructors.
> >
> > That already is not working. There is lot of stuff in crtexe.c and
> > crtdll.c which needs to be called before main / dllmain and is not in
> > __main. If somebody wants to override the default entry point for DLL
> > then the overwritten entry point has to call _CRT_INIT function, this is
> > documented somewhere in MS/WinAPI and mingw-w64 has also all required
> > init parts in _CRT_INIT function.
>
> It's possible to build a program without those. One has to carefully avoid
> triggering pseudo relocation (by adding explicit `dllimport` and disabling
> auto import), and link against a CRT DLL. One may even choose to link
> against libntdllcrt instead of msvcrt or UCRT. It's at least doable.
That is a good point. If somebody do it very carefully, it can work.
>
> > mingw-w64 is already calling gcc's __main() function in crt startup
> > code, so basically gcc is not required to insert manual call of this
> > function to the main function. Moreover gcc does not insert it into
> > wmain function (when compiling with gcc -municode), so it is already
> > inconsistent. Also gcc for linux does not insert this __main into main,
> > so I think it would make sense to allow produce gcc compiler which would
> > not do it neither for windows/mingw-w64.
>
> It's really a GCC issue but I think you can try adding `#undef INVOKE__main`
> in 'gcc/config/i386/cygming.h'.
I looked into released mingw-w64 builds and all since the first released
version are calling __main before main in CRT code. So I think that gcc
should not insert __main into main and I agree that this is gcc issue.
I will open gcc bug report and let it to gcc developers. I guess that
this __main insertion by gcc is because of compatibility with old mingw32.
>
> > > An explanation of why might help as well. If there is a reason to do that,
> > > it would be easier to handle review wise if it is split to a separate
> > > commit
> > > as well, with separate arguments.
> > >
> > > > {
> > > > - unsigned long nptrs = (unsigned long) (ptrdiff_t) __CTOR_LIST__[0];
> > > > + unsigned long nptrs = (unsigned long) __CTOR_LIST__[0];
> > > > unsigned long i;
> > >
> > > This change, to remove the intermediate cast, looks unrelated to the rest
> > > of
> > > the changes. Is there a good reason for why we should do that? In that
> > > case
> > > it could be a separate change. It is also possible that removing it may
> > > reintroduce warnings in some build configuration.
> >
> > I removed it because I though that it is not needed and that ptrdiff_t
> > was the only reason why the new file requires to include any header
> > file.
> >
> > Now when I'm thinking about it, ptrdiff_t is the wrong type at this
> > place. It should be uintptr_t, no? In memory there is stored unsigned
> > integer which has same width as pointer, meaning is number of members
> > and C type of memory for that variable/array is pointer. Meaning is not
> > difference between two pointers.
>
> When using a GNU toolchain, `__CTOR_LIST__` is defined by the linker (in
> 'ld/scripttempl/pe.sc' for 32-bit targets and in 'ld/scripttempl/pep.sc' for
> 64-bit targets) where the first element is always `-1`.
>
> Besides, there's no difference between `intptr_t` and `uintptr_t`; the value
> is truncated to `unsigned long` anyway, so the cast chain is no-op.
This is about ptrdiff_t vs uintptr_t (not inptr_t vs uintptr_t). And it
is just a semantic difference.
_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public