-
Notifications
You must be signed in to change notification settings - Fork 71
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
Segmentation fault with MinGW-w64 due to -lucrt
#196
Comments
AFAIK CPython by default is using ucrt. Is it ok to use msvcrt in C extensions in this case? Indeed -lucrt in a default-msvcrt=msvcrt mingw causes issue. And indeed if -lmsvcrt is an alias, no need to add -lucrt. But if the first question is no, maybe we can do more. |
Yes, it's OK. Only if you pass a libc object to a dll that is linked to an incompatible libc, it will fail. Otherwise, it's fine. For example: // mylib.h
int say_hello(FILE *fp); // mylib.c
#include <stdio.h>
#include "mylib.h"
int say_hello(FILE *fp)
{
return fprintf(fp, "Hello %d world!\n", 42);
} // main.c
#include <stdio.h>
#include "mylib.h"
int main(void)
{
say_hello(stdout);
return 0;
} $ /ucrt64/bin/gcc -shared -Wall mylib.c -o mylib.dll
$ /mingw64/bin/gcc -Wall main.c mylib.dll -o main.exe
$ ./main
zsh: segmentation fault ./main However, Python/C API doesn't need any libc objects, so it doesn't matter. Just like this: // mylib.h
int say_hello(void); // mylib.c
#include <stdio.h>
#include "mylib.h"
int say_hello(void)
{
return fprintf(stdout, "Hello %d world!\n", 42);
} // main.c
#include <stdio.h>
#include "mylib.h"
int main(void)
{
say_hello();
return 0;
} $ /ucrt64/bin/gcc -shared -Wall mylib.c -o mylib.dll
$ /mingw64/bin/gcc -Wall main.c mylib.dll -o main.exe
$ ./main.exe
Hello 42 world! |
The minimal reproducer:
Build and run it in msys2 environment:
This is because mingw64-gcc links msvcrt by default [1], but distutils links ucrt, which causes incompatibility.
It was introduced in #41 and was reported in #109 a year ago. Simply removing
"ucrt"
can fix this.For the relationship between msvcrt and ucrt on MinGW-w64, this post talked about it clearly.
tl; dr:
-lucrt
never works for gcc. On msys2 mingw64 environment, it causes segfault; On msys2 ucrt64 environment, it's a noop. It's not msys2-specific, in fact all MinGW-w64 gcc builds are the same. I have tested on w64devkit and cygwin, the results are at the bottom.In MinGW-w64,
libmsvcrt.a
is just an alias, which varies with--with-default-msvcrt
in the configuration step. By default, it'smsvcrt
, which meanslibmsvcrt.a
is an alias forlibmsvcrt-os.a
. Most MinGW-w64 builds are configured like this, so does msys2 mingw64 environment.[2] In this case, the compiled executable will dynamically link tomsvcrt.dll
.--with-default-msvcrt
can also be set toucrt
, which is msys2 ucrt64 environment does, meanslibmsvcrt.a
is an alias forlibucrt.a
, and the compiled executable will dynamically link toucrtbase.dll
.In both cases, libgcc is implicitly linked with
-lmsvcrt
(remember, it's an alias).So, on msys2 mingw64 environment, libgcc is always linked to msvcrt.dll. If
-lucrt
is passed, the C program will link to ucrtbase.dll, which is incompatible with libgcc and will cause segmentation faults. On msys2 ucrt64 environment, obviously, ucrt is linked implicitly, so it's not necessary to pass-lucrt
.For gcc, if you want the program to link to ucrt properly on a MinGW-w64
--with-default-msvcrt=msvcrt
environment, the only way is to dump gcc's specs and modify it (bygcc -dumpspecs
, which has been metioned in that post). imba-tjd/mingw64ccompiler is doing the right thing.By the way, even the simplest C hello world compiled with
gcc -lucrt
behaves the same here.click to expand
First, generate
hello.c
fromhello.pyx
with cython:msys2 mingw64 prefix
without
-lucrt
with
-lucrt
msys2 ucrt64 prefix
without
-lucrt
with
-lucrt
w64devkit 1.17.0
without
-lucrt
with
-lucrt
cygwin mingw64-gcc
mingw64-x86_64-gcc-core
11.3.0-1
without
-lucrt
with
-lucrt
CC @imba-tjd
The text was updated successfully, but these errors were encountered: