6

I found this in another forum that is supposed to give it to you. But I think this may not be the best way, also I think it results in a memory leak due to the array not being deleted. Is this true?

Also is this the best way? Best way being a cross platform command (if it doesn't exist then use Windows) that gives the folder directory directly.

std::string ExePath() 
{
    using namespace std;

    char buffer[MAX_PATH];

    GetModuleFileName(NULL, buffer, MAX_PATH);

    string::size_type pos = string(buffer).find_last_of("\\/");

    if (pos == string::npos)
    {
        return "";
    }
    else 
    {
        return string(buffer).substr(0, pos);
    }
}
John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Yiannis128
  • 138
  • 1
  • 2
  • 9
  • Define "best way" - since C++17 there's `std::filesystem` which might be considered "better" (since it is part of the standard library). Also you only `delete[]` what you `new[]` (and there is no `new` here) – UnholySheep Jun 16 '18 at 16:26
  • Using boost::filesystem::path – pat Jun 16 '18 at 16:28
  • 1
    Highly platform specific. On Linux, reading the target of the `/proc/self/exe` symlink would be the best option. On other Systems, something else. There's not *one right answer*. – Jesper Juhl Jun 16 '18 at 16:36
  • Possible duplicate of [Finding current executable's path without /proc/self/exe](https://stackoverflow.com/questions/1023306/finding-current-executables-path-without-proc-self-exe). See also [How do I find the location of the executable in C?](https://stackoverflow.com/questions/933850/how-do-i-find-the-location-of-the-executable-in-c) or [Get path of executable](https://stackoverflow.com/questions/1528298/get-path-of-executable). – Vincent Saulue-Laborde Jun 16 '18 at 16:48
  • I don't see a memory leak in that code. – Retired Ninja Jun 16 '18 at 17:56
  • Some operating systems do not even have paths or folders, so it is not going to be *that* cross platform. – Bo Persson Jun 16 '18 at 18:46
  • _I think it results in a memory leak due to the array not being deleted._ What array? The one on the stack? – Paul Sanders Jun 16 '18 at 21:45
  • The char buffer[] array @PaulSanders. But dont memory leaks occur only with pointers? – Yiannis128 Jun 16 '18 at 22:00
  • @Yiannis I think you need to [read a good book](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). – Paul Sanders Jun 16 '18 at 22:04
  • What is this `GetModuleFileName()` function ? Is that specific to a given OS ? If yes, please add relevant tag to question, because it is probably not standard. – kebs Jun 25 '18 at 13:00

2 Answers2

2

There is no memory leak in your code, but there are some issues with it:

  • it is Windows-specific,
  • it works with local code-page and does not support arbitrary Unicode files names.

Unfortunately, there is no standard way of accomplishing this task just with C++ library, but here is a code that will work on Windows and Linux, and support Unicode paths as well. Also it utilizes std::filesystem library from C++17:

#include <filesystem>
#ifdef _WIN32
#include <windows.h>
#elif
#include <unistd.h>
#endif

std::filesystem::path GetExeDirectory()
{
#ifdef _WIN32
    // Windows specific
    wchar_t szPath[MAX_PATH];
    GetModuleFileNameW( NULL, szPath, MAX_PATH );
#else
    // Linux specific
    char szPath[PATH_MAX];
    ssize_t count = readlink( "/proc/self/exe", szPath, PATH_MAX );
    if( count < 0 || count >= PATH_MAX )
        return {}; // some error
    szPath[count] = '\0';
#endif
    return std::filesystem::path{ szPath }.parent_path() / ""; // to finish the folder path with (back)slash
}
Fedor
  • 17,146
  • 13
  • 40
  • 131
2

With macos support:

#include <filesystem>

#ifdef _WIN32
#include <windows.h>
#elif __APPLE__

#include <mach-o/dyld.h>
#include <climits>

#elif
#include <unistd.h>
#endif

std::filesystem::path GetExeDirectory() {
#ifdef _WIN32
    // Windows specific
    wchar_t szPath[MAX_PATH];
    GetModuleFileNameW( NULL, szPath, MAX_PATH );
#elif __APPLE__
    char szPath[PATH_MAX];
    uint32_t bufsize = PATH_MAX;
    if (!_NSGetExecutablePath(szPath, &bufsize))
        return std::filesystem::path{szPath}.parent_path() / ""; // to finish the folder path with (back)slash
    return {};  // some error
#else
    // Linux specific
    char szPath[PATH_MAX];
    ssize_t count = readlink( "/proc/self/exe", szPath, PATH_MAX );
    if( count < 0 || count >= PATH_MAX )
        return {}; // some error
    szPath[count] = '\0';
#endif
}
Alex Zhukov
  • 191
  • 2
  • 5