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
Don't use PCH. But we still need a testcase. 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. We meet this issue when building wxWidgets trunk and Codeblocks using PCH, see http://forums.codeblocks.org/index.php/topic,18383.msg125964.html#msg125964 There is a test case in this post: http://sourceforge.net/p/mingwbuilds/mailman/message/29214215/ 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 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. (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. 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? 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? 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. 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. 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. 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. 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. 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. 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. 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. It would make sense to set this fixed size to 1GB. 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/) Assuming fixed; reopen if there's a problem with more current GCCs. |