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

The class wxTextCtrl is not working while building with "MinGW TDM 64 bit #22639

Closed
EckardKlotz opened this issue Jul 18, 2022 · 13 comments
Closed
Labels
build Any build issue (with or without CMake)
Milestone

Comments

@EckardKlotz
Copy link

Dear Developers.

The class wxTextCtrl is not working while building with "MinGW TDM 64 bit.

If you build wxWidgets as a monolithic 64 bit DLL by using TDM-GCC 10.3.0 you could use in your application not more than on instance of the class wxTextCtrl. Otherwise the application is crashing while destroying the instances. You will already face this issue with the official sample.

Please take look to the "std::streambuf" issue.
In addition you could take a look into your forum: Abnormal program exit

It works only if you modify the header "wx/textctrl.h" as Vadim Zeitlin wrote:

There is something weird with std::streambuf specifically in this TDM
version. In this case you could try editing wx/textctrl.h and setting
wxHAS_TEXT_WINDOW_STREAM to 0 there to disable inheriting wxTextCtrl
from std::streambuf and see if it helps.

Thus I implemented the following change:

#if wxUSE_STD_IOSTREAM
#include "wx/ioswrap.h"
// #define wxHAS_TEXT_WINDOW_STREAM 1
#define wxHAS_TEXT_WINDOW_STREAM 0 // changed by Eckard Klotz 2022.07.10
#else
#define wxHAS_TEXT_WINDOW_STREAM 0
#endif

And yes, if you do so before building the DLL and the application it helps. But this is only a workaround and hope you are able to provide a more professional solution.

Platform and version information

  • wxWidgets version you use: 3.1.5 ... 3.2.0
  • wxWidgets port you use: wxMSW
  • OS and its version:

Edition Windows 10 Home
Version 21H2
Betriebssystembuild 19044.1826
Leistung Windows Feature Experience Pack 120.2212.4180.0

  • Compiler being used: TDM-GCC 10.3.0

Best regards,
Eckard Klotz.

@EckardKlotz EckardKlotz added the build Any build issue (with or without CMake) label Jul 18, 2022
@vadz
Copy link
Contributor

vadz commented Jul 18, 2022

Thanks, but to make this bug report more useful, could you please:

  1. Confirm that it only happens in monolithic build. I have a lot of trouble seeing how can it be related to monolithic/multilib, so it would be really great to have a confirmation that the issue does not happen with the normal multilib build, e.g. using the official binaries for 3.2.0.
  2. Show the minimal change necessary to actually reproduce the problem. Does it happen in the unmodified text sample? If not, could you please provide a minimal diff to it or the minimal sample showing the problem?

TIA!

@EckardKlotz
Copy link
Author

Dear Vadz.

Since I only use a monolithic build DLL of wxWidgets I could not confirm that it is not happening with separate DLLs or with static libraries.

The change I have implemented was done in the wxWidgets header textctrl.h located in

  • [WX_WIDGETS_ROOT]\include\wx\textctrl.zip
  • The change is done in lines 29 and 30.

I have not modified the text sample but the wxWidgets library code.

  • But without modifying the library header the sample is showing the issue.

Actually I thought this issue is already known by you since 2018 since the one who has suggested the workaround "Vadim Zeitlin" seems to be the author of the source-file I have modified.

Best regards,
Eckard Klotz.

@vadz
Copy link
Contributor

vadz commented Jul 18, 2022

Yes, I suggested the workaround because it clearly bypasses the problem entirely. As you said, this is not a proper solution, but I didn't have time to debug the issue back then -- and, to be honest, don't have much more time to do it now neither. So if you could check whether the issue occurs with the multilib build, it would be helpful.

@EckardKlotz
Copy link
Author

Dear Vadz.

The big disadvantage of using small part-libraries is the fact that you have to figure out which you really need.

However, as far as I understand you use the same compiler for your official TDM binary release.
Please tell me which DLLs or static libraries from your official TDM binary release I have to use for linking the sample and I will check for you if the same issue occurs.

  • Please note that I use Code::Blocks for my development and even it is possible to import your Visual Cpp projects I still have to do some manual configurations.
  • Therefore I need your list of DLLs and/or static libraries.

Best regards,
Eckard Klotz.

@vadz
Copy link
Contributor

vadz commented Jul 18, 2022

The big disadvantage of using small part-libraries is the fact that you have to figure out which you really need.

The advantage is that you don't need to link with stuff that you don't need.

However, as far as I understand you use the same compiler for your official TDM binary release. Please tell me which DLLs or static libraries from your official TDM binary release I have to use for linking the sample and I will check for you if the same issue occurs.

You need to link with base and core, and you don't need any MSVS projects. Just replace the mono DLL with the base and core ones in your existing project.

@EckardKlotz
Copy link
Author

Hello Vadz.

As you have advised, I have replaced my monolithic DLL wxmsw32u_gcc_custom.dll by the following 2:

Furthermore I have modified the header wx/textctrl.h again to enable the user of the std::streambuf

#if wxUSE_STD_IOSTREAM
    #include "wx/ioswrap.h"
    #define wxHAS_TEXT_WINDOW_STREAM 1
//    #define wxHAS_TEXT_WINDOW_STREAM 0 // changed by Eckard Klotz 2022.07.10 as sugested at https://groups.google.com/g/wx-users/c/D9vmQWFKgA8/m/BWIlTA5XAAAJ
#else
    #define wxHAS_TEXT_WINDOW_STREAM 0
#endif

I have started the text-sample application and closed it again.

  • It took roundabout 1 minute between pressing the close-button and the crash.
  • This is the same behaviour I already faced with the monolithic DLL and the original header wx/textctrl.h

Please find attached the sample folder with the core and base DLLs taken from the 3.2.0_gcc1030TDM_x64_ReleaseDLL.7z

Attention: Read my PS.: regarding a potential virus-detection in the base DLL.

Best regards,
Eckard.

PS.: I've got an notification from my virus-scanner (Norton 360) when I placed the wxbase32u_gcc1030TDM_x64.dll in my sample-folder. But I ignored it to support you
vc_mswudll_x64.zip
.

@vadz
Copy link
Contributor

vadz commented Jul 18, 2022

OK, thanks, I'll try to debug this.

@EckardKlotz
Copy link
Author

Hello Vadz.

Thank you in advance for all the effort you will take.

Best regards,
Eckard Klotz.

vadz added a commit to vadz/wxWidgets that referenced this issue Jul 18, 2022
When inheriting from std::streambuf, as is the case by default, and
creating wxTextCtrl in the application (as is common) and destroying it
in the library (as is even more so, as it's typically done when the
parent window is destroyed), having inline constructor but not inline
destructor apparently results in std::locale, which is part of
std::streambuf, to be allocated and destroyed using different heaps or
something similar when using TDM-GCC libstdc++, as destroying
std::locale inside the library corrupts the heap and results in crashes
when the next std::locale object is destroyed -- i.e. creating, and then
destroying, more than one wxTextCtrl results in a crash.

Work around this by moving the constructors out of line, as this is
sufficient to avoid the problem, even if it's exact causes are not
exactly clear.

This commit is best viewed with Git --color-moved option.

See wxWidgets#22639.
@vadz
Copy link
Contributor

vadz commented Jul 18, 2022

After spending a couple of hours on this, I finally have a fix, see the PR #22641. I still don't fully understand what's going on here, but TDM-GCC libstdc++ does something weird and doesn't allow creating std::locale in the application but destroying it in the DLL, hence the need for this workaround.

The annoying thing is that this is, of course, not ABI-compatible, so can't be applied to 3.2 as is. But it's clearly worth breaking ABI compatibility for TDM-GCC if this means avoiding crashes... However I don't know how to check for TDM-GCC in the preprocessor, does anybody?

My debugging notes, not really needed any more

I can reproduce the crash. Annoyingly, it doesn't happen in the debug build, but in the release one it crashes on exit due to heap corruption, resulting in warning: Critical error detected c0000374 with the following stack trace

Thread 1 received signal SIGTRAP, Trace/breakpoint trap.
0x00007ff86e9cef13 in ntdll!RtlIsZeroMemory () from C:\WINDOWS\SYSTEM32\ntdll.dll
(gdb) bt
#0  0x00007ff86e9cef13 in ntdll!RtlIsZeroMemory () from C:\WINDOWS\SYSTEM32\ntdll.dll
#1  0x00007ff86e9d7cd2 in ntdll!RtlpNtSetValueKey () from C:\WINDOWS\SYSTEM32\ntdll.dll
#2  0x00007ff86e9d7fba in ntdll!RtlpNtSetValueKey () from C:\WINDOWS\SYSTEM32\ntdll.dll
#3  0x00007ff86e9ddc41 in ntdll!RtlpNtSetValueKey () from C:\WINDOWS\SYSTEM32\ntdll.dll
#4  0x00007ff86e8f5bf0 in ntdll!RtlGetCurrentServiceSessionId () from C:\WINDOWS\SYSTEM32\ntdll.dll
#5  0x00007ff86e8f47b1 in ntdll!RtlFreeHeap () from C:\WINDOWS\SYSTEM32\ntdll.dll
#6  0x00007ff86e809c9c in msvcrt!free () from C:\WINDOWS\System32\msvcrt.dll
#7  0x00007ff82e6e43fd in std::locale::_Impl::~_Impl() () from wxmsw32u_core_gcc_custom.dll
#8  0x00007ff82e6e4950 in std::locale::~locale() () from wxmsw32u_core_gcc_custom.dll
#9  0x00007ff82e2b6fdf in wxTextCtrl::~wxTextCtrl() () from wxmsw32u_core_gcc_custom.dll
#10 0x00007ff74eeea95e in MyTextCtrl::~MyTextCtrl() ()
#11 0x00007ff82e4033dd in wxWindowBase::Destroy() () from wxmsw32u_core_gcc_custom.dll
#12 0x00007ff82e4034fc in wxWindowBase::DestroyChildren() () from wxmsw32u_core_gcc_custom.dll
#13 0x00007ff82e1f20fb in wxWindow::~wxWindow() () from wxmsw32u_core_gcc_custom.dll
#14 0x00007ff74eef0fb2 in MyPanel::~MyPanel() ()
#15 0x00007ff82e4033dd in wxWindowBase::Destroy() () from wxmsw32u_core_gcc_custom.dll
#16 0x00007ff82e4034fc in wxWindowBase::DestroyChildren() () from wxmsw32u_core_gcc_custom.dll
#17 0x00007ff82e1f20fb in wxWindow::~wxWindow() () from wxmsw32u_core_gcc_custom.dll
#18 0x00007ff74eef0f39 in MyFrame::~MyFrame() ()
#19 0x00007ff848d9361e in wxAppConsoleBase::DeletePendingObjects() () from wxbase32u_gcc_custom.dll
#20 0x00007ff848d936b8 in wxAppConsoleBase::ProcessIdle() () from wxbase32u_gcc_custom.dll
#21 0x00007ff82e2e4973 in wxAppBase::ProcessIdle() () from wxmsw32u_core_gcc_custom.dll
#22 0x00007ff848dc5526 in wxEventLoopManual::DoRun() () from wxbase32u_gcc_custom.dll
#23 0x00007ff848dc51ab in wxEventLoopBase::Run() () from wxbase32u_gcc_custom.dll
#24 0x00007ff848d95dac in wxAppConsoleBase::MainLoop() () from wxbase32u_gcc_custom.dll
#25 0x00007ff848e0a0c6 in wxEntryReal(int&, wchar_t**) () from wxbase32u_gcc_custom.dll
#26 0x00007ff74eeb13c1 in __tmainCRTStartup () at C:/crossdev/src/mingw-w64-v8-git/mingw-w64-crt/crt/crtexe.c:333
#27 0x00007ff74eeb14d6 in WinMainCRTStartup () at C:/crossdev/src/mingw-w64-v8-git/mingw-w64-crt/crt/crtexe.c:186

Moreover, I can even reproduce it using this minimal example

#include "wx/app.h"
#include "wx/textctrl.h"
struct MyApp : wxApp {
    bool OnInit() override {
        wxTextCtrl t1;
        wxTextCtrl t2;
        return false;
    }
};
wxIMPLEMENT_APP(MyApp);

i.e. simply destroying the second text control results in this problem as, apparently, destroying the first one corrupts memory. And there is no almost wx code being involved here, as wxTextCtrl default ctor and dtor are pretty trivial.

@PBfordev
Copy link
Contributor

Just for the record: I think this is a rather old issue, discovered in 2020 with TDM 9.2 (only 64-bit version IIRC) and discussed on wx-dev and forum.

And to answer the question from the related PR: WinLibs is a MinGW distribution (unlike nuwen not providing some popular prebuilt libraries but being more up-to-date), aiming to fill a hole left by mingw-64 project not providing their own installer anymore. I know it may be hard to believe, but it seems many people do not like / are not familiar with MSYS2 environment and strongly prefer to use non-MSYS2 up-to-date MinGW distro and building wxWidgets with a makefile.

@vadz
Copy link
Contributor

vadz commented Jul 19, 2022

Yes, thanks, these links were actually given in #22636 in which I had asked to create a separate issue for this problem, but the context got lost, sorry about this.

As for people preferring building with a makefile, I realize that they exist. This is a problem because I have no idea how to maintain the makefiles for them, but, I guess, we'll have to do it somehow...

@vadz
Copy link
Contributor

vadz commented Sep 25, 2022

I've realized that 70c5ec6 (Move wxTextCtrl constructors out of line in wxMSW, 2022-07-18) still wasn't backported to 3.2. I think it should be safe to do it, but it'd be great if somebody could actually confirm it, i.e. build a program with the current wx 3.2 DLLs, then apply this commit, rebuild the DLLs and confirm that the program still runs when using them (and sorry in advance if anybody has already done it and I just forgot about it, but I couldn't find anything like this in the various bugs/PRs associated with this problem).

@vadz vadz added this to the 3.2.2 milestone Sep 25, 2022
@vadz vadz closed this as completed Oct 15, 2022
@vadz
Copy link
Contributor

vadz commented Dec 27, 2022

I've finally tested this myself and as it seems to work fine, I'm backporting this fix to 3.2.

@vadz vadz removed the backport-3.2 Fix applied to master but still has to be backported to stable 3.2 label Dec 27, 2022
vadz added a commit to vadz/wxWidgets that referenced this issue Dec 27, 2022
When inheriting from std::streambuf, as is the case by default, and
creating wxTextCtrl in the application (as is common) and destroying it
in the library (as is even more so, as it's typically done when the
parent window is destroyed), having inline constructor but not inline
destructor apparently results in std::locale, which is part of
std::streambuf, to be allocated and destroyed using different heaps or
something similar when using TDM-GCC libstdc++, as destroying
std::locale inside the library corrupts the heap and results in crashes
when the next std::locale object is destroyed -- i.e. creating, and then
destroying, more than one wxTextCtrl results in a crash.

Work around this by moving the constructors out of line, as this is
sufficient to avoid the problem, even if it's exact causes are not
exactly clear.

This commit is best viewed with Git --color-moved option.

See wxWidgets#22639, wxWidgets#22735.

(cherry picked from commit 70c5ec6)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
build Any build issue (with or without CMake)
Projects
None yet
Development

No branches or pull requests

3 participants