问题
I am writing a program in C that spawns loads of processes and that should report their state via argv[0] so while calling ps
it's easy to see what's going on.
I am aware that initially argv[0] comes with certain memory allocated, that contains the program name (in most cases).
I need however to set much longer string than 20 bytes that contain my program name. My status can be 80-100 characters long.
I made some tests and if I memcpy this longer string into argv[0] it "works for me" but I am afraid that I will start writing into unowned memory and cause segfault which is unacceptable.
How can I safely resize memory allocated for argv[0]?
Sample code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
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;
}
Sample output:
$ ./argv
Current argv[0] length: 6
New argv[0] length: 57
回答1:
To change name display in ps
under Linux, use prctl instead of changing argv[0]
(which is a hack - and this hack doesn't work on everywhere):
int s;
s = prctl(PR_SET_NAME,"myProcess\0",NULL,NULL,NULL);
After this line execution, take a look at ps
, you will see "myProcess" instead of original name.
You are free to pass any string you want to prctl
, regardless original length of argv[0]
. But if your string is more than 16 bytes (including terminating null byte, it will be truncated:
PR_SET_NAME (since Linux 2.6.9)
Set the name of the calling thread, using the value in the location pointed to by (char *) arg2. The name can be up to 16 bytes long, including the terminating null byte. (If the length of the string, including the terminating null byte, exceeds 16 bytes, the string is silently truncated.) This is the same attribute that can be set via pthread_setname_np(3) and retrieved using pthread_getname_np(3). The attribute is likewise accessible via /proc/self/task/[tid]/comm, where tid is the name of the calling thread.
For your question about this:
strncpy(argv[0], my_program_name, strlen(my_program_name)); // Can this segfault?
C99 standard says:
The parameters
argc
andargv
and the strings pointed to by the argv array shall be modifiable by the program, and retain their last-stored values between program startup and program termination.
but you can't increase size of argv[0]
, so you will get an undefined behavior if strlen(my_program_name)
is greater than already allocated memory for argv[0]
: buffer overflow, segfault or anything else because it's UB
来源:https://stackoverflow.com/questions/37321583/setting-argv0-to-longer-value-than-currently-allocated