Установка argv на большее значение, чем в настоящее время

Я пишу программу на C, которая порождает множество процессов и должна сообщать о своем состоянии через argv [0], поэтому при вызове ps легко увидеть, что происходит.

Я знаю, что первоначально argv [0] поставляется с выделенной выделенной памятью, содержащей имя программы (в большинстве случаев).

Однако мне нужно установить гораздо более длинную строку, чем 20 байт, которые содержат мое имя программы. Мое состояние может составлять 80-100 символов.

Я сделал несколько тестов, и если я получу эту более длинную строку в argv [0], она «работает для меня», но я боюсь, что начну писать в незанятую память и вызывать недопустимое segfault.

Как я могу безопасно изменять размер памяти, выделенной для 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 

Чтобы изменить отображение имени в ps под Linux, используйте prctl вместо изменения argv[0] (который является взломом – и этот хак не работает повсюду):

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

После выполнения этой строки взгляните на ps , вы увидите «myProcess» вместо исходного.

Вы можете передать любую строку, которую вы хотите использовать prctl , независимо от исходной длины argv[0] . Но если ваша строка больше 16 байт (включая завершение нулевого байта, она будет усечена:

PR_SET_NAME (начиная с Linux 2.6.9)
Задайте имя вызывающего streamа, используя значение в местоположении, на которое указывает (char *) arg2. Длина имени может быть длиной до 16 байт, включая завершающий нулевой байт. (Если длина строки, включая завершающий нулевой байт, превышает 16 байтов, строка молча усекается.) Это тот же атрибут, который можно установить через pthread_setname_np (3) и получить с помощью pthread_getname_np (3). Атрибут также доступен через / proc / self / task / [tid] / comm, где tid – имя вызывающего streamа.


За ваш вопрос:

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

Стандарт C99 гласит:

Параметры argc и argv и строки, на которые указывает массив argv, могут быть модифицированы программой и сохраняют свои последние сохраненные значения между запуском программы и завершением программы.

но вы не можете увеличить размер argv[0] , так что вы получите неопределенное поведение, если strlen(my_program_name) больше, чем уже выделенная память для argv[0] : переполнение буфера, segfault или что-то еще, потому что это UB