最可靠方式是windows用GetModuleFilenameA、linux/macOS用/proc/self/exe;需检查返回值、处理截断、手动置零、规范化路径;禁用argv[0]和系统dirname函数。

windows 下用 GetModuleFileNameA 获取可执行文件路径
Windows 平台最可靠的方式是调用 WinAPI 的 GetModuleFileNameA,它能准确返回当前进程主模块(即 .exe 文件)的完整路径,不受工作目录影响。
关键点:传入 NULL 作为第一个参数表示获取当前进程的模块路径;第二个参数必须是足够大的缓冲区(通常 MAX_PATH 即 260 字节);第三个参数是缓冲区大小(单位:字符数,不是字节数)。
#include #include #include std::string getExecutablePath() { char buffer[MAX_PATH]; DWORD len = GetModuleFileNameA(NULL, buffer, MAX_PATH); if (len == 0 || len >= MAX_PATH) return ""; return std::String(buffer); }
常见错误:
- 忘记检查返回值是否为 0(调用失败)或是否截断(
len == MAX_PATH) - 误用
GetModuleFileNameW但未正确处理宽字符,导致乱码 - 把结果直接当目录用——需手动截掉最后的文件名,例如用
find_last_of('\')
Linux/macOS 下用 /proc/self/exe 符号链接
Linux 和 macos 可读取 /proc/self/exe 这个符号链接,它始终指向当前进程的可执行文件。这是 POSIX 环境下最通用的方法。
立即学习“C++免费学习笔记(深入)”;
注意:readlink 返回的是符号链接目标路径,可能含相对路径或软链跳转;若程序被重命名或移动,该路径仍有效(因为内核维护的是 inode 引用)。
#include #include #include std::string getExecutablePath() { char buffer[PATH_MAX]; ssize_t len = readlink("/proc/self/exe", buffer, sizeof(buffer) - 1); if (len == -1) return ""; buffer[len] = ' '; return std::string(buffer); }
容易踩的坑:
-
readlink不自动补