C++ Program using <filesystem> Library just does nothing on Windows
Asked Answered
P

1

5

I'm trying to get a program using the <filesystem> library running on Windows. I'm using MSYS2's (64 Bit) g++.

#include <iostream>
#include <filesystem>

int main()
{
    std::cout << "Hello World\n";
    std::cout << "Current path is " << std::filesystem::current_path() << '\n';
}

I'm building it with

g++ -std=c++17 -Wall -Werror -Wextra main.cpp -lstdc++fs

I get no console output from the compiler. It silently generates an a.exe. Executing the a.exe just does nothing. There is no output and no errors. $? (which is said to contain a program's return code) is 127 after running the program.

g++ -v prints:

Using built-in specs.
COLLECT_GCC=C:\msys64\mingw64\bin\g++.exe
COLLECT_LTO_WRAPPER=C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/9.1.0/lto-wrapper.exe
Target: x86_64-w64-mingw32
Configured with: ../gcc-9.1.0/configure --prefix=/mingw64 --with-local-prefix=/mingw64/local --build=x86_64-w64-mingw32 --host=x86_64-w64-mingw32 --target=x86_64-w64-mingw32 --with-native-system-header-dir=/mingw64/x86_64-w64-mingw32/include --libexecdir=/mingw64/lib --enable-bootstrap --with-arch=x86-64 --with-tune=generic --enable-languages=c,lto,c++,fortran,ada,objc,obj-c++ --enable-shared --enable-static --enable-libatomic --enable-threads=posix --enable-graphite --enable-fully-dynamic-string --enable-libstdcxx-filesystem-ts=yes --enable-libstdcxx-time=yes --disable-libstdcxx-pch --disable-libstdcxx-debug --disable-isl-version-check --enable-lto --enable-libgomp --disable-multilib --enable-checking=release --disable-rpath --disable-win32-registry --disable-nls --disable-werror --disable-symvers --enable-plugin --with-libiconv --with-system-zlib --with-gmp=/mingw64 --with-mpfr=/mingw64 --with-mpc=/mingw64 --with-isl=/mingw64 --with-pkgversion='Rev3, Built by MSYS2 project' --with-bugurl=https://sourceforge.net/projects/msys2 --with-gnu-as --with-gnu-ld
Thread model: posix
gcc version 9.1.0 (Rev3, Built by MSYS2 project)

What could be wrong?

(I get a Hello World output and $? is 0, if I comment out the line with the std::filesystem::current_path() call, so the compiler is working.)

Pollie answered 25/7, 2019 at 18:47 Comment(11)
Try adding std::cout << std::endl; Maybe the data isn't getting flushed to standard out.Graecoroman
non zero exit code indicates that program failed to run. Perhaps you should ensure that runtime library is available.Andean
Your code itself is correct, and when I compile and run it on linux I get the output I'd expect (it prints hello world, then the current path). This means that the program isn't loading the right library, but that's all I knowCodon
@Graecoroman Just tried that. No luck. :( @VTT Running ldd on the executable lists no errors. However, there are three DLLs taken from MinGW64, which might be outdated. I'm looking how to make it use the ones from MSYS64 right now.Pollie
current_path can throw exceptions. See here: en.cppreference.com/w/cpp/filesystem/current_pathPricillaprick
@MichaelMahn I tried using the variant with the error_code and print that after the call. Still nothing printed at all.Pollie
The next thing I'd be tempted to do is use process monitor (from SysinternalsSuite) to monitor that process and see what it is up to. You might also get lucky with the windows application event log.Graecoroman
Before throwing external tools at the problem, build your program in debug mode, run in debugger and single-step into current_path(). At some point, the WinAPI GetCurrentDirectory() will propably be called. See if it fails.Windbroken
gdb says During startup program exited with code 0xc0000139.Pollie
@Neon Looks like there is an issue with some dll your program is trying to load. learn.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/… 0xC0000139 STATUS_ENTRYPOINT_NOT_FOUND {Entry Point Not Found} The procedure entry point %hs could not be located in the dynamic link library %hs. I'd look in event viewer in the Windows application log to see if there's more information about which dll and entry point are causing the problem.Graecoroman
Yes, I found the problem. I was using the Git Bash thinking it wouldn't make any difference, but actually it uses its own MinGW setup. I was using the g++ from MSYS, but the DLLs from Git Bash. It works when using the native MSYS terminal. I will write an answer soon.Pollie
P
9

Thanks to the commenters for dropping some ideas that finally led me to finding a solution.

TL;DR

If you have various MinGW-based tool sets installed (e.g. Cygwin, MinGW, MSYS, Git Bash), use the shell shipped with the set. Only carefully add the mingw*/bin paths to PATH; rather stick to the default PATH setup of the respective shell. Click here, if you want to have convenient context menu shortcuts for the MSYS shell.


A Story about a million MinGWs

The problem was due to my weird local setup. Over the time I accumulated various versions of MinGW spread all over my computer. If I needed a utility, say diff, I would google it and download something from somewhere (often sourceforge), install it to somewhere and add the bin folder to my PATH. This strategy worked for most things.

Toolsets I've installed over the time, including but not restricted to:

  • MinGW (32 and 64)
  • Cygwin
  • MSYS
  • Git (+ Git Bash)

For some long time now I have mostly been using the Git Bash for everything. Lately I wanted to get the newest g++ compiler and stuff and found that MSYS2 has a package manager (pacman) and pretty up to date packages so I installed it. And added it to the PATH, then used the Git Bash.

However, each toolset coming with its own shell does its own PATH magic and has its own MinGW copy. So I made my Git Bash use the MSYS2 g++, but applications executed from the Git Bash still used DLLs from Git Bash's MinGW copy. I don't know for sure, but I think it's very probably that this was the problem.

For finding out, I used the following in the Git Bash:

# because of my PATH adjustment, I got the right g++
$ which g++
/c/msys64/mingw64/bin/g++

# my program uses DLLs from /mingw64, though
$ ldd a.exe
        ntdll.dll => /c/Windows/SYSTEM32/ntdll.dll (0x77060000)
        kernel32.dll => /c/Windows/system32/kernel32.dll (0x76e40000)
        KERNELBASE.dll => /c/Windows/system32/KERNELBASE.dll (0x7fefcc00000)
        msvcrt.dll => /c/Windows/system32/msvcrt.dll (0x7fefcf70000)
        libgcc_s_seh-1.dll => /mingw64/bin/libgcc_s_seh-1.dll (0x61440000)
        libwinpthread-1.dll => /mingw64/bin/libwinpthread-1.dll (0x64940000)
        libstdc++-6.dll => /mingw64/bin/libstdc++-6.dll (0x6fc40000)
        USER32.dll => /c/Windows/system32/USER32.dll (0x76f60000)
        GDI32.dll => /c/Windows/system32/GDI32.dll (0x7fefddb0000)
        LPK.dll => /c/Windows/system32/LPK.dll (0x7fefd540000)
        USP10.dll => /c/Windows/system32/USP10.dll (0x7fefdbe0000)

# with cygpath I can find out that this is actually the Git Bash's installation
$ cygpath -w /mingw64
C:\Program Files\Git\mingw64

MSYS2 comes with its own shell, which sets up its PATH correctly so the application works. In the MSYS2 shell:

$ ./a.exe
Hello World
Current path is "E:\\temporary\\2019_07_25-gpp_filesystem_test"

For the unlikely event someone got into a similar trouble and would like to use the MSYS2 shell more easily in various folders, check out this repo with a reg script setting up convenient context menu shortcuts for the MSYS2 shell: https://github.com/njzhangyifei/msys2-mingw-shortcut-menus

Pollie answered 25/7, 2019 at 20:52 Comment(4)
Thank you for posting this answer! When someone has a weird problem it really helps to have theseCodon
You made my day!Ephebe
Now, do you know of an easy way to get along all this with eclipse ? I mean of a way of switching between all these gcc to force eclipse to use one, without having to play constantly with the PATH env var ?Ephebe
If you're talking about C++ development in Eclipse, doesn't it ship with its own toolset? I would use the default setup (and compile through Eclipse).Pollie

© 2022 - 2024 — McMap. All rights reserved.