web-dev-qa-db-ja.com

Cで実行可能ファイルの場所を見つけるにはどうすればよいですか?

C/C++で現在実行されているプログラムの場所(フルパス)を見つける方法はありますか?

argv[0]の問題は、完全なパスを提供しないことです。)

140
eran

要約する:

  • _/proc_を使用するUnixでは、本当にストレートで現実的な方法は次のとおりです。

    • readlink("/proc/self/exe", buf, bufsize)(Linux)

    • readlink("/proc/curproc/file", buf, bufsize)(FreeBSD)

    • readlink("/proc/self/path/a.out", buf, bufsize)(Solaris)

  • _/proc_のないUnix(上記が失敗した場合):

    • Argv [0]が「/」(絶対パス)で始まる場合、これがパスです。

    • それ以外の場合、argv [0]に "/"(相対パス)が含まれている場合、cwdに追加します(まだ変更されていない場合)。

    • それ以外の場合は、実行可能_$PATH_について_argv[0]_のディレクトリを検索します。

    その後、実行可能ファイルが実際にシンボリックリンクではないかどうかを確認するのが妥当かもしれません。解決される場合は、symlinkディレクトリに関連して解決します。

    この手順は、/ procメソッドでは必要ありません(少なくともLinuxの場合)。 procシンボリックリンクは、実行可能ファイルを直接指します。

    _argv[0]_を正しく設定するのは呼び出しプロセス次第であることに注意してください。ほとんどの場合は正しいですが、呼び出しプロセスを信頼できない場合があります(例:setuid実行可能ファイル)。

  • Windowsの場合:GetModuleFileName(NULL, buf, bufsize)を使用します

188
lispmachine

Windowsを使用している場合は、 GetModuleFileName() 関数を使用します。

21
Shino C G

以下のコメントはUNIXのみであることに注意してください。

この質問に対する舌な答えは、すべての場合にこの質問に正しく答える一般方法がないということです。発見したように、argv [0]は親プロセスによって何にでも設定できるため、プログラムの実際の名前やファイルシステム内の場所とはまったく関係ありません。

ただし、次のヒューリスティックはしばしば機能します。

  1. Argv [0]が絶対パスの場合、これが実行可能ファイルへのフルパスであると想定します。
  2. Argv [0]が相対パス、つまり/を含む場合、getcwd()を使用して現在の作業ディレクトリを特定し、それにargv [0]を追加します。
  3. Argv [0]がプレーンなWordの場合、$ PATHでargv [0]を探し、見つけたディレクトリにargv [0]を追加します。

これらのすべては、問題のプログラムを呼び出したプロセスによって回避できることに注意してください。最後に、emg-2で言及されているようなLinux固有の手法を使用できます。他のオペレーティングシステムにはおそらく同等のテクニックがあります。

上記の手順で有効なパス名が与えられたとしても、実際に必要なパス名がまだない場合があります(実際にやりたいのはどこかに構成ファイルを見つけることだと思うので)。ハードリンクが存在するということは、次のような状況が発生する可能性があることを意味します。

-- assume /app/bin/foo is the actual program
$ mkdir /some/where/else
$ ln /app/bin/foo /some/where/else/foo     # create a hard link to foo
$ /some/where/else/foo

さて、上記のアプローチ(/ proc/$ pid/exeを含む)は、プログラムへの実際のパスとして/some/where/else/fooを提供します。そして、実際には、それはaプログラムへの実際のパスであり、あなたが望むものではありません。この問題は、実際にはハードリンクよりもはるかに一般的なシンボリックリンクでは発生しないことに注意してください。

このアプローチは原則として信頼性が低いという事実にもかかわらず、実際にはほとんどの目的に対して十分に機能します。

17
Dale Hagglund

実際には答えではなく、覚えておくべきメモです。

ご覧のとおり、実行可能な実行可能ファイルの場所を見つける問題は、LinuxおよびUnixで非常に注意が必要であり、プラットフォーム固有です。それを行う前に、よく考えてください。

構成ファイルまたはリソースファイルを検出するために実行可能ファイルの場所が必要な場合は、システムにファイルを配置するUnixの方法に従う必要があります。putconfigs to /etc または /usr/local/etcまたは現在のユーザーのホームディレクトリ、および/usr/shareは、リソースファイルを置くのに適した場所です。

10
Michael

多くのPOSIXシステムでは、/ proc/PID/exeの下にあるsimlinkを確認できます。いくつかの例:

# file /proc/*/exe
/proc/1001/exe: symbolic link to /usr/bin/distccd
/proc/1023/exe: symbolic link to /usr/sbin/sendmail.sendmail
/proc/1043/exe: symbolic link to /usr/sbin/crond
6
anon

Unixシステムでは、バイナリは起動されてから削除された可能性があることに注意してください。 Unixでは完全に合法で安全です。最後に、Windowsで実行中のバイナリを削除できないことを確認しました。

/ proc/self/exeは引き続き読み取り可能ですが、実際には機能するシンボリックリンクではありません。それは...奇妙になります。

4
Thomas

Mac OS Xでは、 _NSGetExecutablePath

見る - man 3 dyld および この回答 同様の質問。

3
Tim Ruddick

Linuxの場合は、/proc/self/exe binrelocと呼ばれる素敵なライブラリにバンドルされていることを行う方法は、次の場所にあります。

3
Grumbel

私は...するだろう

1)basename()関数を使用します: http://linux.die.net/man/3/basename
2)そのディレクトリへのchdir()
3)getpwd()を使用して現在のディレクトリを取得します

そうすれば、。/や../bin/ではなく、きちんとした完全な形でディレクトリを取得できます。

プログラムで重要な場合は、現在のディレクトリを保存して復元することをお勧めします。

0
JCCyC