使用 MinGW 中的 GCC 4.8.1 编译 GLib 2.38.1,执行 valac 编译会报如下错误:
ERROR:gspawn-win32-helper.c:226:WinMain: assertion failed: (__argc >= ARG_COUNT) |
阅读代码 glib/gspawn-win32-helper.c 发现此程序依赖于 __argc 和 __argv 全局变量进行参数访问,但有相关说明这两个全局变量是由 Microsoft 编译和 msvcrt.dll 提供,调试发现使用 MinGW 编译的 gspawn-win32-helper.exe 无论是否在命令行下进行都会导致上述错误,而且打印发现 __argc 永远是 0。
查看 /mingw/include/stdlib.h 会发现还有一组访问参数相关的全局变量 _argc 和 _argv,验证后是可行的。解决问题,下面是补丁文件:
From ebe6e6989b49bd119acc2d29b2f8ad0b6bb03313 Mon Sep 17 00:00:00 2001 From: Heiher <root@heiher.info> Date: Wed, 30 Oct 2013 22:17:29 +0800 Subject: [PATCH] glib/gspawn-win32-helper.c: Fix get arguments for GCC compiler. --- glib/gspawn-win32-helper.c | 61 ++++++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/glib/gspawn-win32-helper.c b/glib/gspawn-win32-helper.c index 7896941..8d2bcbd 100644 --- a/glib/gspawn-win32-helper.c +++ b/glib/gspawn-win32-helper.c @@ -222,28 +222,35 @@ main (int ignored_argc, char **ignored_argv) _CrtSetReportMode(_CRT_ASSERT, 0); #endif +#ifdef _MSC_VER // for Microsoft compiler +#define __ARGC __argc +#define __ARGV __argv +#else // for GCC compiler (MinGW) +#define __ARGC _argc +#define __ARGV _argv +#endif - g_assert (__argc >= ARG_COUNT); + g_assert (__ARGC >= ARG_COUNT); /* Fetch the wide-char argument vector */ __wgetmainargs (&argc, &wargv, &wenvp, 0, &si); - /* We still have the system codepage args in __argv. We can look + /* We still have the system codepage args in __ARGV. We can look * at the first args in which gspawn-win32.c passes us flags and - * fd numbers in __argv, as we know those are just ASCII anyway. + * fd numbers in __ARGV, as we know those are just ASCII anyway. */ - g_assert (argc == __argc); + g_assert (argc == __ARGC); /* argv[ARG_CHILD_ERR_REPORT] is the file descriptor number onto * which write error messages. */ - child_err_report_fd = atoi (__argv[ARG_CHILD_ERR_REPORT]); + child_err_report_fd = atoi (__ARGV[ARG_CHILD_ERR_REPORT]); /* Hack to implement G_SPAWN_FILE_AND_ARGV_ZERO. If * argv[ARG_CHILD_ERR_REPORT] is suffixed with a '#' it means we get * the program to run and its argv[0] separately. */ - if (__argv[ARG_CHILD_ERR_REPORT][strlen (__argv[ARG_CHILD_ERR_REPORT]) - 1] == '#') + if (__ARGV[ARG_CHILD_ERR_REPORT][strlen (__ARGV[ARG_CHILD_ERR_REPORT]) - 1] == '#') argv_zero_offset++; /* argv[ARG_HELPER_SYNC] is the file descriptor number we read a @@ -252,16 +259,16 @@ main (int ignored_argc, char **ignored_argv) * duplicate the process handle we sent it. Duplicating a handle * from another process works only if that other process exists. */ - helper_sync_fd = atoi (__argv[ARG_HELPER_SYNC]); + helper_sync_fd = atoi (__ARGV[ARG_HELPER_SYNC]); /* argv[ARG_STDIN..ARG_STDERR] are the file descriptor numbers that * should be dup2'd to 0, 1 and 2. '-' if the corresponding fd * should be left alone, and 'z' if it should be connected to the * bit bucket NUL:. */ - if (__argv[ARG_STDIN][0] == '-') + if (__ARGV[ARG_STDIN][0] == '-') ; /* Nothing */ - else if (__argv[ARG_STDIN][0] == 'z') + else if (__ARGV[ARG_STDIN][0] == 'z') { fd = open ("NUL:", O_RDONLY); if (fd != 0) @@ -272,7 +279,7 @@ main (int ignored_argc, char **ignored_argv) } else { - fd = atoi (__argv[ARG_STDIN]); + fd = atoi (__ARGV[ARG_STDIN]); if (fd != 0) { dup2 (fd, 0); @@ -280,9 +287,9 @@ main (int ignored_argc, char **ignored_argv) } } - if (__argv[ARG_STDOUT][0] == '-') + if (__ARGV[ARG_STDOUT][0] == '-') ; /* Nothing */ - else if (__argv[ARG_STDOUT][0] == 'z') + else if (__ARGV[ARG_STDOUT][0] == 'z') { fd = open ("NUL:", O_WRONLY); if (fd != 1) @@ -293,7 +300,7 @@ main (int ignored_argc, char **ignored_argv) } else { - fd = atoi (__argv[ARG_STDOUT]); + fd = atoi (__ARGV[ARG_STDOUT]); if (fd != 1) { dup2 (fd, 1); @@ -301,9 +308,9 @@ main (int ignored_argc, char **ignored_argv) } } - if (__argv[ARG_STDERR][0] == '-') + if (__ARGV[ARG_STDERR][0] == '-') ; /* Nothing */ - else if (__argv[ARG_STDERR][0] == 'z') + else if (__ARGV[ARG_STDERR][0] == 'z') { fd = open ("NUL:", O_WRONLY); if (fd != 2) @@ -314,7 +321,7 @@ main (int ignored_argc, char **ignored_argv) } else { - fd = atoi (__argv[ARG_STDERR]); + fd = atoi (__ARGV[ARG_STDERR]); if (fd != 2) { dup2 (fd, 2); @@ -322,19 +329,19 @@ main (int ignored_argc, char **ignored_argv) } } - /* __argv[ARG_WORKING_DIRECTORY] is the directory in which to run the + /* __ARGV[ARG_WORKING_DIRECTORY] is the directory in which to run the * process. If "-", don't change directory. */ - if (__argv[ARG_WORKING_DIRECTORY][0] == '-' && - __argv[ARG_WORKING_DIRECTORY][1] == 0) + if (__ARGV[ARG_WORKING_DIRECTORY][0] == '-' && + __ARGV[ARG_WORKING_DIRECTORY][1] == 0) ; /* Nothing */ else if (_wchdir (wargv[ARG_WORKING_DIRECTORY]) < 0) write_err_and_exit (child_err_report_fd, CHILD_CHDIR_FAILED); - /* __argv[ARG_CLOSE_DESCRIPTORS] is "y" if file descriptors from 3 + /* __ARGV[ARG_CLOSE_DESCRIPTORS] is "y" if file descriptors from 3 * upwards should be closed */ - if (__argv[ARG_CLOSE_DESCRIPTORS][0] == 'y') + if (__ARGV[ARG_CLOSE_DESCRIPTORS][0] == 'y') for (i = 3; i < 1000; i++) /* FIXME real limit? */ if (i != child_err_report_fd && i != helper_sync_fd) if (_get_osfhandle (i) != -1) @@ -360,16 +367,16 @@ main (int ignored_argc, char **ignored_argv) child_err_report_fd = dup_noninherited (child_err_report_fd, _O_WRONLY); helper_sync_fd = dup_noninherited (helper_sync_fd, _O_RDONLY); - /* __argv[ARG_WAIT] is "w" to wait for the program to exit */ - if (__argv[ARG_WAIT][0] == 'w') + /* __ARGV[ARG_WAIT] is "w" to wait for the program to exit */ + if (__ARGV[ARG_WAIT][0] == 'w') mode = P_WAIT; else mode = P_NOWAIT; - /* __argv[ARG_USE_PATH] is "y" to use PATH, otherwise not */ + /* __ARGV[ARG_USE_PATH] is "y" to use PATH, otherwise not */ - /* __argv[ARG_PROGRAM] is executable file to run, - * __argv[argv_zero_offset]... is its argv. argv_zero_offset equals + /* __ARGV[ARG_PROGRAM] is executable file to run, + * __ARGV[argv_zero_offset]... is its argv. argv_zero_offset equals * ARG_PROGRAM unless G_SPAWN_FILE_AND_ARGV_ZERO was used, in which * case we have a separate executable name and argv[0]. */ @@ -379,7 +386,7 @@ main (int ignored_argc, char **ignored_argv) */ protect_wargv (wargv + argv_zero_offset, &new_wargv); - if (__argv[ARG_USE_PATH][0] == 'y') + if (__ARGV[ARG_USE_PATH][0] == 'y') handle = _wspawnvp (mode, wargv[ARG_PROGRAM], (const wchar_t **) new_wargv); else handle = _wspawnv (mode, wargv[ARG_PROGRAM], (const wchar_t **) new_wargv); -- 1.8.4.2 |
Over!