mokky14's IT diary

IT関係の仕事メモ、勉強会の感想など書いてます。

C言語でmainのargvを書き換えると

Cソースのレビュー中に「main関数のargvの値を書き換えたらまずいのか?」という議論があったので少し調べてみたら、psで表示されるプロセス名が変わるということが分かった。

 

参考にしたのは以下のページ

http://slashdot.jp/journal/443359/argv%5B0%5D%E3%81%AF%E4%BD%95%E3%82%92%E3%81%95%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B%E3%81%8B

 

試しにサンプル作って確認してみた。起動してから20秒後にargv[1]を書き換える。

#include <stdio.h>
#include <unistd.h>
#include <string.h>

int main(int argc, char* argv[]) {
        sleep(20);

        strcpy(argv[1], "change-arg");
        puts("change argument");

        sleep(20);

        return 0;
}

 

実行。

$ cc changearg.c 
$ ./a.out "before-change-argument"
change argument

 

プロセス起動直後のps結果。

$ ps x|grep a.out|grep -v grep
 7440 pts/2    T      0:00 ./a.out
27129 pts/1    S+     0:00 ./a.out before-change-argument

 

プロセス起動20秒後のps結果。第一引数の先頭部分がstrcpyした文字列に変更されている。

$ ps x|grep a.out|grep -v grep
 7440 pts/2    T      0:00 ./a.out
27129 pts/1    S+     0:00 ./a.out change-arg ge-argument

ということで、argvの値を変更するようなプログラミングはやらない方が良さそう。

 

(おまけ)

argvの値を変更すると、どこで保持している情報が変更になるのか気になったので調べてみた。

プロセスに関することなので、/proc配下のファイルだろうと推測。

$ ps x|grep a.out|grep -v grep
1321 pts/1 S+ 0:00 ./a.out before-change-argument
7440 pts/2 T 0:00 ./a.out 
$ cd /proc/1321
$ ls
attr             cpuset   fd      loginuid  mountstats  root       statm
auxv             cwd      fdinfo  maps      numa_maps   schedstat  status
cmdline          environ  io      mem       oom_adj     smaps      task
coredump_filter  exe      limits  mounts    oom_score   stat       wchan

名前からすると、cmdlineというファイルが怪しそう

$ cat cmdline 
./a.outbefore-change-argument 
$ od -x cmdline 
0000000 2f2e 2e61 756f 0074 6562 6f66 6572 632d 
0000020 6168 676e 2d65 7261 7567 656d 746e 0000 
0000037

20秒後のcmdlineの値。やはり値が書き換わっていた。

$ cat cmdline
./a.outchange-argge-argument
$ od -x cmdline
0000000 2f2e 2e61 756f 0074 6863 6e61 6567 612d
0000020 6772 6700 2d65 7261 7567 656d 746e 0000
0000037