Open nurelin opened 5 years ago
ok, i am not sure but I think this is caused by this line
https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/src/c%2B%2B17/fs_ops.cc#L1395
Why do you think the problem is with that line? The macro __MINGW64_VERSION_MAJOR
has the same value for 32 and 64 bits variant (MINGW64
is about the Mingw-w64 project, not about 32/64 bits execution mode).
BTW, I can replicate the problem (after fixing the source code, please use copy&paste from the original test case).
Unfortunately, gdb does not help. catch throw
does not work, and trying to step into the function doesn't work either. This is going to require a debug build of libstdc++.
You are right, that makes no sense
Ok, I have rebuilt mingw-w64-i686-gcc
.
std::filesystem::__gnu_posix::stat (path=0xe774f8 L"C:\\Users\\nurelin\\AppData\\Local\\Temp\\", buffer=0x64fdbc) at ../../../../../../gcc-9.1.0/libstdc++-v3/src/c++17/../filesystem/ops-common.h:77
77 { return ::_wstat(path, buffer); }
This the call to _wstat
which fails but I don't know if the function belongs to the mingw-w64-crt
or to msvcrt.dll
since I cannot step in the function.
@nurelin : is the pointer buffer
valid before calling _wstat
? That function is sensitive to the value of the macro _USE_32BIT_TIME_T
. If the macro was defined where the structure pointed by buffer
was allocated, it must be defined too on the call site to _wstat
. Same for the undefined case.
I doubt that _wstat
itself is the problem here.
(gdb) p st
$2 = {st_dev = 1024, st_ino = 70, st_mode = 522, st_nlink = 32240, st_uid = 115, st_gid = -520, st_rdev = 6618804, st_size = 36, st_atime = 6618588, st_mtime = 0, st_ctime = 0}
(gdb) ptype st
type = struct _stat32 {
_dev_t st_dev;
_ino_t st_ino;
unsigned short st_mode;
short st_nlink;
short st_uid;
short st_gid;
_dev_t st_rdev;
_off_t st_size;
__time32_t st_atime;
__time32_t st_mtime;
__time32_t st_ctime;
}
The values are wrong because I printed the variable when uninitialized. But from the types of the structure, it seems that it is using this
And since the status is defined by this typedef which point to this which would tells that the macro _USE_32BIT_TIME_T
is likely to be defined.
But I do not know how to tell which version of *stat*()
is called for sure. Maybe removing the inlining ?
Or do I need to recompile gcc after recompiling mingw-w64-i686-crt ?
That's 32 bit time_t indeed. You can try replacing the call to _wstat
with a call to _wstat32
or _wstat32i64
depending on the size of the _off_t
data member (32/64 bits) inside of std::filesystem::__gnu_posix::stat
, rebuild libstdc++ and see if that the crash goes away.
And/Or you can add something like
printf("%d %d\n", &_wstat == &_wstat32, &_wstat == &_wstat32i64);
to check which variant is being called.
In file included from ../../../../../gcc-9.1.0/libstdc++-v3/src/c++17/fs_ops.cc:57:
../../../../../gcc-9.1.0/libstdc++-v3/src/c++17/../filesystem/ops-common.h: In function 'int std::filesystem::__gnu_posix::stat(const wchar_t*, std::filesystem::__gnu_posix::stat_type*)':
../../../../../gcc-9.1.0/libstdc++-v3/src/c++17/../filesystem/ops-common.h:78:28: warning: self-comparison always evaluates to true [-Wtautological-compare]
78 | printf("%d %d", &_wstat == &_wstat32, &_wstat == &_wstat32i64);
| ^~ ~~~~~~~~~
In file included from C:/msys32_test/mingw32/i686-w64-mingw32/include/wchar.h:424,
from C:/msys32_test/home/nurelin/MINGW-packages/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libstdc++-v3/include/cwchar:44,
from C:/msys32_test/home/nurelin/MINGW-packages/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libstdc++-v3/include/bits/postypes.h:40,
from C:/msys32_test/home/nurelin/MINGW-packages/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libstdc++-v3/include/iosfwd:40,
from C:/msys32_test/home/nurelin/MINGW-packages/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libstdc++-v3/include/system_error:40,
from C:/msys32_test/home/nurelin/MINGW-packages/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libstdc++-v3/include/bits/fs_fwd.h:35,
from C:/msys32_test/home/nurelin/MINGW-packages/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libstdc++-v3/include/filesystem:36,
from ../../../../../gcc-9.1.0/libstdc++-v3/src/c++17/fs_ops.cc:31:
../../../../../gcc-9.1.0/libstdc++-v3/src/c++17/../filesystem/ops-common.h:78:54: error: comparison between distinct pointer types 'int (__attribute__((cdecl)) *)(const wchar_t*, _stat32*)' and 'int (__attribute__((cdecl)) *)(const wchar_t*, _stati64*)' lacks a cast [-fpermissive]
78 | printf("%d %d", &_wstat == &_wstat32, &_wstat == &_wstat32i64);
| ^~~~~~~~~~~
In file included from ../../../../../gcc-9.1.0/libstdc++-v3/src/c++17/fs_ops.cc:57,
from ../../../../../gcc-9.1.0/libstdc++-v3/src/c++17/cow-fs_ops.cc:26:
../../../../../gcc-9.1.0/libstdc++-v3/src/c++17/../filesystem/ops-common.h: In function 'int std::filesystem::__gnu_posix::stat(const wchar_t*, std::filesystem::__gnu_posix::stat_type*)':
../../../../../gcc-9.1.0/libstdc++-v3/src/c++17/../filesystem/ops-common.h:78:28: warning: self-comparison always evaluates to true [-Wtautological-compare]
78 | printf("%d %d", &_wstat == &_wstat32, &_wstat == &_wstat32i64);
| ^~ ~~~~~~~~~
In file included from C:/msys32_test/mingw32/i686-w64-mingw32/include/wchar.h:424,
from C:/msys32_test/home/nurelin/MINGW-packages/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libstdc++-v3/include/cwchar:44,
from C:/msys32_test/home/nurelin/MINGW-packages/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libstdc++-v3/include/bits/postypes.h:40,
from C:/msys32_test/home/nurelin/MINGW-packages/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libstdc++-v3/include/iosfwd:40,
from C:/msys32_test/home/nurelin/MINGW-packages/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libstdc++-v3/include/system_error:40,
from C:/msys32_test/home/nurelin/MINGW-packages/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libstdc++-v3/include/bits/fs_fwd.h:35,
from C:/msys32_test/home/nurelin/MINGW-packages/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libstdc++-v3/include/filesystem:36,
from ../../../../../gcc-9.1.0/libstdc++-v3/src/c++17/fs_ops.cc:31,
from ../../../../../gcc-9.1.0/libstdc++-v3/src/c++17/cow-fs_ops.cc:26:
../../../../../gcc-9.1.0/libstdc++-v3/src/c++17/../filesystem/ops-common.h:78:54: error: comparison between distinct pointer types 'int (__attribute__((cdecl)) *)(const wchar_t*, _stat32*)' and 'int (__attribute__((cdecl)) *)(const wchar_t*, _stati64*)' lacks a cast [-fpermissive]
78 | printf("%d %d", &_wstat == &_wstat32, &_wstat == &_wstat32i64);
| ^~~~~~~~~~~
Seems that the underlying function called is _wstat32()
which further hints that the _USE_32BIT_TIME_T
macro is defined.
I think that this _wstat()
function should be called instead of the _wstat32()
from msvcrt since it tries to fixup its argument using the _mingw_no_trailing_slash()
function.
I have something interesting:
In a mingw32 environment:
nurelin@PC MINGW32 ~
$ cat wstat_test.cpp
#include <iostream>
#include <sys/stat.h>
int main()
{
std::wstring s { L"C:\\msys32_test\\tmp\\" };
struct _stat32 buf;
std::wcout << s << std::endl;
int result = _wstat32(s.c_str(), &buf);
std::cout << result << std::endl;
std::wstring s2 { L"C:\\msys32_test\\tmp" };
struct _stat32 buf2;
std::wcout << s2 << std::endl;
int result2 = _wstat32(s2.c_str(), &buf2);
std::cout << result2 << std::endl;
}
nurelin@PC MINGW32 ~
$ g++ wstat_test.cpp
nurelin@PC MINGW32 ~
$ ./a.exe
C:\msys32_test\tmp\
-1
C:\msys32_test\tmp
0
but in a mingw64 environment:
nurelin@PC MINGW64 ~
$ cat wstat_test.cpp
#include <iostream>
#include <sys/stat.h>
int main()
{
std::wstring s { L"C:\\msys32_test\\tmp\\" };
struct _stat64i32 buf;
std::wcout << s << std::endl;
int result = _wstat64i32(s.c_str(), &buf);
std::cout << result << std::endl;
std::wstring s2 { L"C:\\msys32_test\\tmp" };
struct _stat64i32 buf2;
std::wcout << s2 << std::endl;
int result2 = _wstat64i32(s2.c_str(), &buf2);
std::cout << result2 << std::endl;
}
nurelin@PC MINGW64 ~
$ g++ wstat_test.cpp
nurelin@PC MINGW64 ~
$ ./a
C:\msys32_test\tmp\
0
C:\msys32_test\tmp
0
It seems that mingw-w64 has fixed the behavior of _wstat64i32()
(https://sourceforge.net/p/mingw-w64/bugs/643/).
Looks like _wstat32()
could use something similar.
@nurelin : please make sure that the mingw-w64 folks know about this. Thanks.
Pinging @katietz and @msarahan, though this is 32-bit only, and MSYS2, it might be nice to try to fix this as part of a final update of packages from MSYS2/mingw-64 i686, though I expect Kai would like to fix this anyway.
i686 GCC is rotting badly though (numerical precision is getting worse) and it's not just rotting on Windows, it is also the case on Linux IMHO.
Mingw32:
Mingw64:
Am I the only one affected ?