Finding current executable's path without /proc/self/exe

前端 未结 13 816
有刺的猬
有刺的猬 2020-11-22 01:06

It seems to me that Linux has it easy with /proc/self/exe. But I\'d like to know if there is a convenient way to find the current application\'s directory in C/C++ with cros

相关标签:
13条回答
  • 2020-11-22 01:29

    In addition to mark4o's answer FreeBSD also has

    const char* getprogname(void)
    

    It should also be available in MacOS. It's available in GNU/Linux through libbsd.

    0 讨论(0)
  • 2020-11-22 01:30

    Some OS-specific interfaces:

    • Mac OS X: _NSGetExecutablePath() (man 3 dyld)
    • Linux: readlink /proc/self/exe
    • Solaris: getexecname()
    • FreeBSD: sysctl CTL_KERN KERN_PROC KERN_PROC_PATHNAME -1
    • FreeBSD if it has procfs: readlink /proc/curproc/file (FreeBSD doesn't have procfs by default)
    • NetBSD: readlink /proc/curproc/exe
    • DragonFly BSD: readlink /proc/curproc/file
    • Windows: GetModuleFileName() with hModule = NULL

    There are also third party libraries that can be used to get this information, such as whereami as mentioned in prideout's answer, or if you are using Qt, QCoreApplication::applicationFilePath() as mentioned in the comments.

    The portable (but less reliable) method is to use argv[0]. Although it could be set to anything by the calling program, by convention it is set to either a path name of the executable or a name that was found using $PATH.

    Some shells, including bash and ksh, set the environment variable "_" to the full path of the executable before it is executed. In that case you can use getenv("_") to get it. However this is unreliable because not all shells do this, and it could be set to anything or be left over from a parent process which did not change it before executing your program.

    0 讨论(0)
  • 2020-11-22 01:30

    If you ever had to support, say, Mac OS X, which doesn't have /proc/, what would you have done? Use #ifdefs to isolate the platform-specific code (NSBundle, for example)?

    Yes isolating platform specific code with #ifdefs is the conventional way this is done.

    Another approach would be to have a have clean #ifdef-less header wich contains function declarations and put the implementations in platform specific source files. For example, check out how Poco C++ library does something similar for their Environment class.

    0 讨论(0)
  • 2020-11-22 01:33

    Well, of course, this doesn't apply to all projects. Still, QCoreApplication::applicationFilePath() never failed me in 6 years of C++/Qt development.

    Of course, one should read documentation thoroughly before attempting to use it:

    Warning: On Linux, this function will try to get the path from the /proc file system. If that fails, it assumes that argv[0] contains the absolute file name of the executable. The function also assumes that the current directory has not been changed by the application.

    To be honest, I think that #ifdef and other solutions like that shouldn't be used in modern code at all.

    I'm sure that smaller cross-platform libraries also exist. Let them encapsulate all that platform-specific stuff inside.

    0 讨论(0)
  • 2020-11-22 01:33

    But I'd like to know if there is a convenient way to find the current application's directory in C/C++ with cross-platform interfaces.

    You cannot do that (at least on Linux)

    Since an executable could, during execution of a process running it, rename(2) its file path to a different directory (of the same file system). See also syscalls(2) and inode(7).

    On Linux, an executable could even (in principle) remove(3) itself by calling unlink(2). The Linux kernel should then keep the file allocated till no process references it anymore. With proc(5) you could do weird things (e.g. rename(2) that /proc/self/exe file, etc...)

    In other words, on Linux, the notion of a "current application's directory" does not make any sense.

    Read also Advanced Linux Programming and Operating Systems: Three Easy Pieces for more.

    Look also on OSDEV for several open source operating systems (including FreeBSD or GNU Hurd). Several of them provide an interface (API) close to POSIX ones.

    Consider using (with permission) cross-platform C++ frameworks like Qt or POCO, perhaps contributing to them by porting them to your favorite OS.

    0 讨论(0)
  • 2020-11-22 01:34

    You can use argv[0] and analyze the PATH environment variable. Look at : A sample of a program that can find itself

    0 讨论(0)
提交回复
热议问题