2014-03-08

有趣的 main 函数参数

Views: 9602 | 6 Comments

大家都知道, C 语言可执行程序的入口是 main 函数, main 函数的原型是这样:

int main(int argc, char **argv);

编译程序生成可执行文件后, 从命令行运行, 参数 argc 是指命令行参数的个数(包括程序本身), 而参数 argv 则是所有参数字符串.

你有没有想过, 为什么 argv 的类型是 char**, 而不是 const char** 呢? 难道 argv 的内容也可以被修改? 没错! 命令行传过来的参数是可以被修改的. 而修改后能带来什么好处呢? 其实, 你可以通过修改 argv 来更改进程在 top/ps 中的显示. 例如, 如果你的可执行文件是 a.out, 那么你可以让它在 top/ps 显示成 abc, 也就是修改进程的名字.

可以看看下面的代码:

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

int main(int argc, char **argv){
	strcpy(argv[0], "hi!");
	getchar();
	return 0;
}

把代码保存为 a.c, 编译并运行程序:

gcc a.c; ./a.out

这个程序会卡住, 这时, 你打开另一个命令行, 执行 ps aux | grep a.out, 你会找不到这个程序的进程. 如果执行 ps aux | grep hi, 进程就出现了.

Related posts:

  1. 关于 C++ 中的函数指针
  2. Libevent 2 HTTP 客户端示例
  3. 小心递归次数限制
  4. PHP的continue 2
  5. 如何解读 SSDB 的 log
Posted by ideawu at 2014-03-08 11:35:23

6 Responses to "有趣的 main 函数参数"

  • 很奇怪,argv[0]是在堆上吧,占多少空间?假如strcpy(argv[0], "hiiiiiiiii!");会越界吧 Reply
    @Yemsheng: 为什么在堆上面啊,能解释下吗? Reply
    @shincepu:
    应该在栈上。

    int main(int argc, char **argv) {
    strcpy(argv[0], "123456789abcdef");
    printf("%s\n", argv[0]);
    printf("%s\n", argv[1]);
    getchar();
    return 0;
    }

    ./a.out hehe
    123456789abcdef
    9abcdef

    可以看到hehe被覆盖了。这样有可能会存在隐患。

    如果这样会不会好一点
    int len = strlen(argv[0]);
    strncpy(argv[0], "123456789abcdef", len); Reply
    @Yemsheng: @Yemsheng: 不在堆也不在栈上。命令行参数和环境变量放在进程虚拟内存比栈更高的地址处。 Reply
    @Yemsheng: 恩,我试了下:用free或者delete。调试报错。 Reply
  • Funny. Reply

Leave a Comment