Bug 56926

Summary: Crash (without ICE) while compiling Boost.Math
Product: gcc Reporter: Ruben Van Boxem <vanboxem.ruben>
Component: c++Assignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: normal CC: asmwarrior, i.nixman, ismail, xunxun1982
Priority: P3    
Version: 4.8.1   
Target Milestone: ---   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2013-04-12 00:00:00

Description Ruben Van Boxem 2013-04-11 19:13:47 UTC
When compiling the file libs\math\build\..\src\tr1\assoc_laguerre.cpp from Boost 1.52.0 or 1.53.0 (perhaps any other version is affected too), GCC causes a dirty crash providing me no way of getting a sensible backtrace or providing a preprocessed source for reproduction. The compile command is:

"g++"  -ftemplate-depth-128 -O0 -fno-inline -Wall -g -mthreads -fvisibility=hidden -Winvalid-pch -DBOOST_ALL_NO_LIB=1 -DBOOST_BUILD_PCH_ENABLED -I"bin.v2\libs\math\build\gcc-mingw-4.8.1\debug\link-static\threading-multi\..\src\tr1" -I"." -I"libs\math\src\tr1" -c -o "bin.v2\libs\math\build\gcc-mingw-4.8.1\debug\link-static\threading-multi\assoc_laguerre.o" "libs\math\build\..\src\tr1\assoc_laguerre.cpp"

This does not happen with GCC 4.7. If there is anything I can try to give more output, please let me know. The crash happens before -save-temps outputs anything.

The binaries are for Windows 64-bit and available here (but require Win64, I haven't tested the Linux binaries built with the exact same build process):
http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/rubenvb/gcc-4.8-release/x86_64-w64-mingw32-gcc-4.8.0-win64_rubenvb.7z/download
Comment 1 Richard Biener 2013-04-12 08:42:20 UTC
Don't use PCH.  But we still need a testcase.
Comment 2 Ruben Van Boxem 2013-05-13 13:48:56 UTC
As bugzilla has a file size limit of 1000kB, here's a link to my dropbox containing a zipped gch file that I believe is responsible for the crash.

https://dl.dropboxusercontent.com/u/58715553/pch.hpp.gch.zip

This file was created with GCC 4.8.1 20130425.

Alternatively (if you have a 64-bit Windows (virtual)box) just download
http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/rubenvb/gcc-4.8-release/x86_64-w64-mingw32-gcc-4.8.0-win64_rubenvb.7z

and Boost
http://sourceforge.net/projects/boost/files/boost/1.53.0/

and add the mingw64/bin extracted directory to PATH, and run
bootstrap toolset=gcc
b2 toolset=gcc

which will slowly compile Boost up to Boost.Math, which will result in several crashes.
Comment 3 asmwarrior 2013-10-10 01:38:54 UTC
We meet this issue when building wxWidgets trunk and Codeblocks using PCH, see http://forums.codeblocks.org/index.php/topic,18383.msg125964.html#msg125964
Comment 4 asmwarrior 2013-10-15 00:57:49 UTC
There is a test case in this post: http://sourceforge.net/p/mingwbuilds/mailman/message/29214215/
Comment 5 baltic 2013-12-27 22:10:45 UTC
Experience the same while trying to build a project with massive amounts of Qt headers in a pch. Happens with mingw64 builds for versions 4.8.0 4.8.1 and 4.8.2
Can upload the pch, if needed. worked fine with 4.6
Comment 6 asmwarrior 2013-12-28 09:22:38 UTC
It is very simple to reproduce this bug. Here is the steps I do
1, download the GCC 4.8.2 from MinGW-w64 site, I'm using i686-4.8.2-release-posix-dwarf-rt_v3-rev1

2, download the boost source package, I'm using boost_1_55_0.7z download from boost official site, extract its source to some folder like: D:\mingw-builds\boost_1_55_0.  (Note, no need to build boost library, only the boost header files are needed for testing)

3, create a simple file named "pch.h", which contains following:
--------------------
#ifndef pch_h
#define pch_h

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor"

#include <boost/asio.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/program_options.hpp>
#include <boost/thread.hpp>

#pragma GCC diagnostic pop
#endif
-------------------- 

4, create a simple "test.cpp" file, which contains following:
--------------------
#include "pch.h"

int main()
{
	int a;
	int b;
	int c;
	a++;
	b++;
}
--------------------

5, build the pch file by running the command.

g++.exe -Wall -fexceptions  -g  -march=core2 -Wall -ID:\mingw-builds\boost_1_55_0  -c pch.h -o pch.h.gch

6, now, you will see a file named "pch.h.gch" was generated, its size is bigger than 200M.

7, compile the test.cpp file by running the command:
g++.exe -v -Wall -fexceptions  -g  -march=core2 -Wall -ID:\mingw-builds\boost_1_55_0  -Winvalid-pch -include pch.h -c test.cpp -o test.o

8, I see some verbose messages, but no "test.o" file was generated in the working directory, also I see no crash dialog shown.

So, this is indeed a bug.

Now, if you comment out some lines in the pch.h file, e.g. only leave the first #include directive: #include <boost/asio.hpp>, and comment out the later three include directive, and run the steps again, you get a 47M pch.h.gch and a 206K test.o file.

I try to use GDB to catch the errors, but failed.
Try use GDB, I did such thing:
gdb g++.exe [enter]
then
set args -v -Wall -fexceptions  -g  -march=core2 -Wall -ID:\mingw-builds\boost_1_55_0  -Winvalid-pch -include pch.h -c test.cpp -o test.o [enter]
then
r [enter]

GDB can't catch anything, just the same as I run the command in the Command line, the last message from GDB is: [Inferior 1 (process 2000) exited with code 01]

Does exit code "01" has some special meaning?

BTW: I have test the GCC 4.9 snapshot i686-4.9.0-snapshot-20131119-rev205009-posix-dwarf-rt_v4.7z from mingw-w64 site, it has the same bug.
Comment 7 baltic 2013-12-28 13:42:05 UTC
(In reply to baltic from comment #5)
> worked fine with 4.6
This is not true anymore :) was probably working fine with previous versions of the Qt, because headers were smaller back than. Now 4.6 version of MinGW-64 doesn't work with the PCH's full of Qt headers either.
Comment 8 Emma 2014-02-26 01:14:44 UTC
Probably I'd better add some comments here, even though the problem was not caused by compiling boost. Well, it is crashed because compiling large precompiled header file. Any progress to solve the problem?
Comment 9 Andre Netzeband 2014-10-15 22:48:18 UTC
Hello

I'm using MingW64 with GCC 4.9.1 (x86_64-4.9.1-posix-seh-rt_v3-rev1) and tried to precompile some Boost Headers to speed up compiling.
Unfortunately I get the same error described here: It crashed and windows just show the following information:

  Problemereignisname:	APPCRASH
  Anwendungsname:	cc1plus.exe
  Anwendungsversion:	0.0.0.0
  Anwendungszeitstempel:	00000000
  Fehlermodulname:	cc1plus.exe
  Fehlermodulversion:	0.0.0.0
  Fehlermodulzeitstempel:	00000000
  Ausnahmecode:	c0000005
  Ausnahmeoffset:	0000000000923688
  Betriebsystemversion:	6.1.7601.2.1.0.256.48
  Gebietsschema-ID:	1031
  Zusatzinformation 1:	50fa
  Zusatzinformation 2:	50fa4f6a0bed1a7f9bb7018c9ff4ca3f
  Zusatzinformation 3:	7510
  Zusatzinformation 4:	751099e505bceb2fa8cbac2f21c93fb2

This issue was reported over one year ago. Was there any progress?
Comment 10 Andre Netzeband 2014-11-08 22:00:44 UTC
Once again the question: The original error report is around 1,5 years old. I can hardly believe that there has been absolutely no progress so far.
Comment 11 asmwarrior 2015-05-20 13:42:01 UTC
Today, I did the same test as in comment 6 with a more recent gcc 5.1(http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/dongsheng-daily/5.x/gcc-5-win32_5.1.1-20150512.7z/download), but I still get the same bad result.
Comment 12 asmwarrior 2015-05-22 02:37:58 UTC
Hi, I just did a test on the cygwin 32bit tool chain.
1, download the cygwin installer.
2, install  gcc-g++ 4.9.2 and boost 1.57 package
3, run the steps in comment 6, except that you don't need to add the "-ID:\mingw-builds\boost_1_55_0" in the build command, because we can use the boost library installed from the previous step. 
4, when building the pch files, I get a 318M pch.h.gch file
5, when building the object file, I get a 365K test.o file

So, this bug doesn't happen in the cygwin tool chain, and it looks like the bug only happens in the MinGW and MinGW-W64 tool chain.

Any ideas what is the reason of this bug? Maybe, someone can supply a debug version of g++, and let help to run under GDB.
Comment 13 asmwarrior 2015-05-22 07:31:12 UTC
I did some further test with the condition I stated in comment 11. That is gcc 5.1.
Now, I have pch.h.gch file (about 200M) already generated.
First thing, I try to see whether preprocessor works OK, so I add the "-E" option.
For test.cpp file
------
#include "pch.h"

int main()
{
	int a;
	int b;
	int c;
	a++;
	b++;
}
------
Run the command:
g++.exe -v -E -Wall -fexceptions  -g -march=core2 -Wall -ID:\mingw-builds\boost_1_55_0  -Winvalid-pch -include pch.h test.cpp -o have-include.i

Then I comment out the first line
------
//#include "pch.h"

int main()
{
	int a;
	int b;
	int c;
	a++;
	b++;
}
------
Then run the command below:
g++.exe -v -E -Wall -fexceptions  -g -march=core2 -Wall -ID:\mingw-builds\boost_1_55_0  -Winvalid-pch -include pch.h test.cpp -o no-include.i

Then I compare the result:
Both "have-include.i" and "no-include.i" are about 7M, I see the they are nearly the same, expect the "have-include.i" have two extra lines.

Here is the have-include.i
------
...
...
#pragma GCC diagnostic pop
# 1 "<command-line>" 2
# 1 "test.cpp"
# 1 "pch.h" 1
# 2 "test.cpp" 2

int main()
{
 int a;
 int b;
 int c;
 a++;
 b++;
}
-------
Here is no-include.i
------
...
...
#pragma GCC diagnostic pop
# 1 "<command-line>" 2
# 1 "test.cpp"



int main()
{
 int a;
 int b;
 int c;
 a++;
 b++;
}
------

Now, I try to build those .i files to object files with those command:
g++.exe -v -Wall -fexceptions  -g -march=core2 -Wall -c no-include.i -o no-include.o
g++.exe -v -Wall -fexceptions  -g -march=core2 -Wall -c have-include.i -o have-include.o
Result is:
I get the same result "no-include.o" and "have-include.o". (Yes, they are exactly same in every bytes)

Now, I did other test like below:
g++.exe -v -Wall -fexceptions  -g -march=core2 -Wall -ID:\mingw-builds\boost_1_55_0  -Winvalid-pch -include pch.h -c test.cpp -o have-include-c.o -save-temps

Here, I have "-save-temps" put in the command option, I get no "have-include-c.o" file generated, also I get an empty "test.ii" generated.
Here is the log:
------
...
...
 D:\mingw-builds\boost_1_55_0
 e:\code\gcc\dongsheng-daily\gcc-5-win32\bin\../lib/gcc/i686-w64-mingw32/5.1.1/../../../../include/c++/5.1.1
 e:\code\gcc\dongsheng-daily\gcc-5-win32\bin\../lib/gcc/i686-w64-mingw32/5.1.1/../../../../include/c++/5.1.1/i686-w64-mi
ngw32
 e:\code\gcc\dongsheng-daily\gcc-5-win32\bin\../lib/gcc/i686-w64-mingw32/5.1.1/../../../../include/c++/5.1.1/backward
 e:\code\gcc\dongsheng-daily\gcc-5-win32\bin\../lib/gcc/i686-w64-mingw32/5.1.1/include
 e:\code\gcc\dongsheng-daily\gcc-5-win32\bin\../lib/gcc/i686-w64-mingw32/5.1.1/include-fixed
 e:\code\gcc\dongsheng-daily\gcc-5-win32\bin\../lib/gcc/i686-w64-mingw32/5.1.1/../../../../i686-w64-mingw32/include
End of search list.


------

Now, if I remove the "-save-temps" option, and run below:
g++.exe -v -Wall -fexceptions  -g -march=core2 -Wall -ID:\mingw-builds\boost_1_55_0  -Winvalid-pch -include pch.h -c test.cpp -o have-include-c.o

Still no "have-include-c.o" file, but this time, the log message has some extra lines:
------
...
...
 D:\mingw-builds\boost_1_55_0
 e:\code\gcc\dongsheng-daily\gcc-5-win32\bin\../lib/gcc/i686-w64-mingw32/5.1.1/../../../../include/c++/5.1.1
 e:\code\gcc\dongsheng-daily\gcc-5-win32\bin\../lib/gcc/i686-w64-mingw32/5.1.1/../../../../include/c++/5.1.1/i686-w64-mi
ngw32
 e:\code\gcc\dongsheng-daily\gcc-5-win32\bin\../lib/gcc/i686-w64-mingw32/5.1.1/../../../../include/c++/5.1.1/backward
 e:\code\gcc\dongsheng-daily\gcc-5-win32\bin\../lib/gcc/i686-w64-mingw32/5.1.1/include
 e:\code\gcc\dongsheng-daily\gcc-5-win32\bin\../lib/gcc/i686-w64-mingw32/5.1.1/include-fixed
 e:\code\gcc\dongsheng-daily\gcc-5-win32\bin\../lib/gcc/i686-w64-mingw32/5.1.1/../../../../i686-w64-mingw32/include
End of search list.
GNU C++ (GCC) version 5.1.1 20150512 (i686-w64-mingw32)
        compiled by GNU C version 5.1.1 20150512, GMP version 5.1.3, MPFR version 3.1.2-p11, MPC version 1.0.3
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: af290162d8f9d7b22486b8d9679fb0bb

------

So, it looks like happens after the preprocessor has successfully read the pch file, when it(cc1plus.exe) try to start the parsing, it get crashed, but under my Windows XP, I don't see any message or dialog shown up when it crashed.
Comment 14 asmwarrior 2015-05-23 02:22:41 UTC
The bug can be seen when "-E" and "-fpch-preprocess" is used together to generate a preprocessed file.
If I have a small pch file named "spch.h" and "spch.h.gch"(note the spch.h.gch size is about 47M), and if I have a test.cpp like below:
------
#include "spch.h"

int main()
{
	int a;
	int b;
	int c;
	a++;
	b++;
}
------

Then, run the command:
g++.exe -v -E -Wall -fexceptions  -g -march=core2 -Wall -ID:\mingw-builds\boost_1_55_0  -Winvalid-pch -include spch.h test.cpp -fpch-preprocess -o xxx.ii -ftime-report

I will get a xxx.ii containing such contents:
------
# 1 "test.cpp"
# 1 "D:\\mingw-builds\\test-51//"
# 1 "<built-in>"
# 1 "<command-line>"
#pragma GCC pch_preprocess "./spch.h.gch"
# 1 "test.cpp"
# 1 "spch.h" 1
# 2 "test.cpp" 2

int main()
{
 int a;
 int b;
 int c;
 a++;
 b++;
}
------

You see, the line "#pragma GCC pch_preprocess "./spch.h.gch"" is generated correctly, which means G++ load the pch file correctly. (That's what the -fpch-preprocess option used for, see: https://gcc.gnu.org/onlinedocs/gcc/Preprocessor-Options.html)

But if I use a big pch file "pch.h.gch", and run the similar command line like above, I don't see any .ii file generated, which means G++ crashed before log out the line "#pragma GCC pch_preprocess ...".

By reading the source code, I see that in gcc-4.9.2\gcc\c-family\c-ppoutput.c, there is a function:

/* Load in the PCH file NAME, open on FD.  It was originally searched for
   by ORIG_NAME.  Also, print out a #include command so that the PCH
   file can be loaded when the preprocessed output is compiled.  */

static void
cb_read_pch (cpp_reader *pfile, const char *name,
	     int fd, const char *orig_name ATTRIBUTE_UNUSED)
{
  c_common_read_pch (pfile, name, fd, orig_name);

  fprintf (print.outf, "#pragma GCC pch_preprocess \"%s\"\n", name);
  print.src_line++;
}

So, the bug happens before the fprintf() function, maybe inside the c_common_read_pch function call. 

I would like to see anyone can supply a debug version of 32bit cc1plus.exe, so that I can hunt the bug further under GDB, because building the whole gcc tool chain is too difficult for me.
Comment 15 asmwarrior 2015-05-31 06:34:43 UTC
I think the bug has already reported more than ten years ago, see: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=14940

There are many fixes in various hosts, but not included the windows hosts. As Kai suggest in the post: https://sourceforge.net/p/mingw-w64/bugs/382/
We need a windows host fix.
Comment 16 asmwarrior 2015-05-31 07:59:11 UTC
I think I may find some hard coded which limit the pch file size, it is located in: gcc/config/i386/host-mingw32.c

You can view the file in
https://gcc.gnu.org/git/?p=gcc.git;a=blob_plain;f=gcc/config/i386/host-mingw32.c;hb=HEAD

There are some code around the line 45

/* FIXME: Is this big enough?  */
static const size_t pch_VA_max_size  = 128 * 1024 * 1024;

It is about 128M as I can see.

So, I would suggest to set a larger value of this variable, and try to see it could accept a larger pch file.
Comment 17 asmwarrior 2015-06-02 05:10:36 UTC
Good news, I can definitely confirm that enlarge the value: pch_VA_max_size can solve the crash issue.

Luckily, the value is defined in host-mingw32.c is a const value:
static const size_t pch_VA_max_size  = 128 * 1024 * 1024;
And there are only three references in the host-mingw32.c.

Since I don't have the ability to build the gcc under windows myself, today, I try to edit the cc1plus.exe in a binary editor.
That is: find the three references instructions in the cc1plus.exe, and edit the instructions, so that I changed the pch_VA_max_size value from 128M to 512M.
128 * 1024 * 1024 = 128M = 08 00 00 00 (Hex)
512M = 20 00 00 00 (Hex)

To find the places where those three instructions locates, there is a trick.

I use the tool named "ollydbg" version 1.1 which is a debugger and also a disassembler. 
Open the file cc1plus.exe, and let ollydbg show a table containing all the calls to external modules. 


Two references is located in the function body:
--------
static void *
mingw32_gt_pch_get_address (size_t size, int fd  ATTRIBUTE_UNUSED)
{
  void* res;
  size = (size + va_granularity - 1) & ~(va_granularity - 1);
  if (size > pch_VA_max_size)
    return NULL;

  /* FIXME: We let system determine base by setting first arg to NULL.
     Allocating at top of available address space avoids unnecessary
     fragmentation of "ordinary" (malloc's)  address space but may not
     be safe  with delayed load of system dll's. Preferred addresses
     for NT system dlls is in 0x70000000 to 0x78000000 range.
     If we allocate at bottom we need to reserve the address as early
     as possible and at the same point in each invocation. */
 
  res = VirtualAlloc (NULL, pch_VA_max_size,
		      MEM_RESERVE | MEM_TOP_DOWN,
		      PAGE_NOACCESS);
  if (!res)
    w32_error (__FUNCTION__, __FILE__, __LINE__, "VirtualAlloc");
  else
    /* We do not need the address space for now, so free it.  */
    VirtualFree (res, 0, MEM_RELEASE);

  return res; 
}
--------
Then, you can search the calling table by "VirtualAlloc" from the table, you will find only one match, then go the address of the calling instruction, you can easily find the two instructions which has "00000008" in the instructions. Then, change the last byte to "20", note that "00000020" is in fact 20 00 00 00 which is 512M because x86 cpu uses little endian.

The third place can be found in the function body:
--------
static int
mingw32_gt_pch_use_address (void *addr, size_t size, int fd,
			    size_t offset)
{
  void * mmap_addr;
  HANDLE mmap_handle;
 
  /* Apparently, MS Vista puts unnamed file mapping objects into Global
     namespace when running an application in a Terminal Server
     session.  This causes failure since, by default, applications 
     don't get SeCreateGlobalPrivilege. We don't need global
     memory sharing so explicitly put object into Local namespace.

     If multiple concurrent GCC processes are using PCH functionality,
     MapViewOfFileEx returns "Access Denied" error.  So we ensure the
     session-wide mapping name is unique by appending process ID.  */

#define OBJECT_NAME_FMT "Local\\MinGWGCCPCH-"

  char* object_name = NULL;
  /* However, the documentation for CreateFileMapping says that on NT4
     and earlier, backslashes are invalid in object name.  So, we need
     to check if we are on Windows2000 or higher.  */
  OSVERSIONINFO version_info;
  int r;

  version_info.dwOSVersionInfoSize = sizeof (version_info);

  if (size == 0)
    return 0; 

  /* Offset must be also be a multiple of allocation granularity for
     this to work.  We can't change the offset. */ 
  if ((offset & (va_granularity - 1)) != 0 || size > pch_VA_max_size)
    return -1;


  /* Determine the version of Windows we are running on and use a
     uniquely-named local object if running > 4.  */
  GetVersionEx (&version_info);
--------
Now, search for the function call of "GetVersionEx", you can easily find and change the instruction.


The total changes can be listed in the patch window of ollydbg, see the screen shot
http://imagizer.imageshack.us/v2/689x223q90/673/xL8rmw.png
(The cc1plus.exe I used to modify is the one I tested in comment 11)
Then, you can save the modified cc1plus.exe, and now, it can handle larger pch file up to 512M.

Good luck.
Comment 18 İsmail Dönmez 2015-06-02 08:08:21 UTC
It would make sense to set this fixed size to 1GB.
Comment 19 asmwarrior 2015-06-28 08:50:08 UTC
Martin Richter has post a patch to solve this issue, see: [Comment 47](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=14940#c47), also there are some discussion in [MinGW-w64 - for 32 and 64 bit Windows / Bugs / #382 PCH: cc1plus.exe crash on Windows8.1](https://sourceforge.net/p/mingw-w64/bugs/382/)
Comment 20 Marek Polacek 2019-06-08 15:02:27 UTC
Assuming fixed; reopen if there's a problem with more current GCCs.