将argv 设置为比当前分配的值更长的值

我正在用C语言编写一个程序来生成大量进程,并且应该通过argv [0]报告它们的状态,所以在调用ps很容易看出发生了什么。

我知道最初argv [0]带有一定的内存分配,包含程序名称(在大多数情况下)。

但是,我需要设置比包含程序名称的20个字节更长的字符串。 我的状态可以是80-100个字符。

我做了一些测试,如果我把这个更长的字符串记忆到argv [0]中它“对我有效”但我担心我会开始写入无主内存并导致段错误,这是不可接受的。

如何安全地调整为argv [0]分配的内存?

示例代码:

 #include  #include  #include  char* generate_really_long_program_name() { return strdup("here is something that generates really long program name\0"); } int main (int argc, char *argv[]) { printf("Current argv[0] length: %zu\n", strlen(argv[0])); char* my_program_name = generate_really_long_program_name(); strncpy(argv[0], my_program_name, strlen(my_program_name)); // Can this segfault? free(my_program_name); printf("New argv[0] length: %zu\n", strlen(argv[0])); return 0; } 

样本输出:

 $ ./argv Current argv[0] length: 6 New argv[0] length: 57 

要在Linux下更改ps名称显示,请使用prctl而不是更改argv[0] (这是一个hack – 而且这个hack在任何地方都不起作用):

 int s; s = prctl(PR_SET_NAME,"myProcess\0",NULL,NULL,NULL); 

执行此行后,看看ps ,您将看到“myProcess”而不是原始名称。

无论原始长度为argv[0] ,您都可以自由传递任何想要传递的字符串。 但是如果你的字符串超过16个字节(包括终止空字节,它将被截断:

PR_SET_NAME(自Linux 2.6.9起)
使用(char *)arg2指向的位置中的值设置调用线程的名称。 名称最长可达16个字节,包括终止空字节。 (如果字符串的长度(包括终止空字节)超过16个字节,则会以静默方式截断字符串。)这是可以通过pthread_setname_np(3)设置并使用pthread_getname_np(3)检索的相同属性。 该属性同样可以通过/ proc / self / task / [tid] / comm访问,其中tid是调用线程的名称。


对于你的问题:

 strncpy(argv[0], my_program_name, strlen(my_program_name)); // Can this segfault? 

C99标准说:

参数argcargv以及argv数组指向的字符串应该可由程序修改,并在程序启动和程序终止之间保留它们最后存储的值。

但你不能增加argv[0]大小,所以如果strlen(my_program_name)大于argv[0]已经分配的内存,你将得到一个未定义的行为:缓冲区溢出,段错误或其他任何因为它是UB