изменение аргументов командной строки - PullRequest
1 голос
/ 16 апреля 2010

Я пишу программу на Си. Он берет свои аргументы из командной строки. Я хочу изменить аргументы commandLine в коде. Поскольку они определены как "const char *", я не могу изменить их с помощью "strcpy", "memcpy", ... Кроме того, вы знаете, я не могу просто изменить их тип с "const char *" на "char * ». Есть ли способ их поменять?

Заранее большое спасибо.

С уважением, Шади.

Ответы [ 4 ]

7 голосов
/ 16 апреля 2010

Согласно C99 §5.1.2.2.1 / 1, подпись для main равна

int main(int argc, char *argv[]) { /* ... */ }

Таким образом, вы можете удалить const. Только не вызывайте переполнение буфера из-за strcpy в более длинных строках, чем исходные аргументы, или при попытке установить больше аргументов, чем было передано изначально.

Все остальные в основном правы, что вы должны создать копию вместо этого.

2 голосов
/ 16 апреля 2010

Нет, вам не разрешено изменять их. Тем не менее, нет никаких правил, запрещающих копировать их в новый буфер и использовать вместо них.

1 голос
/ 16 апреля 2010

Возможно, это не относится к делу, но вы ничего не можете изменить ни с помощью strcpy (), ни memcpy (); суффикс «cpy» - сокращение от копии (неудивительно).

Что касается изменения указателя argv, вы, конечно, можете изменить указатель, но почему? Если вы хотите, чтобы аргументы командной строки отличались от заданных, просто игнорируйте их и используйте любые значения, которые вы предпочитаете. Также обратите внимание, что argv является параметром и, следовательно, локальным по отношению к main (); если это необходимо где-то еще, вы должны либо передать его как параметр, либо сохранить как глобальную переменную.

0 голосов
/ 29 июля 2016

Неважно, если вы измените const char * на char * основной функции.

Единственное, о чем вы должны заботиться, это переполнение буфера strcpy.

В соответствии со спецификацией ELF (см. Рисунок 3-31 компоновка стека), http://refspecs.linuxbase.org/elf/abi386-4.pdf, за областью функциональных параметров следует область значений среды.

argv - это массив указателей на каждый параметр, а также Environment - это массив указателей на каждую среду var = value string. Таким образом, макет, как показано ниже.

argv[0]  --> 1st parameter
argv[1]  --> 2nd parameter
argv[2]  --> 3rd parameter
...
NULL
--------------------------------------- memory boundary between param and env
environ[0] --> 1st env_var=env_value
environ[1] --> 2nd env_var=env_value
environ[2] --> 3rd env_var=env_value
...
NULL

Так что, если вы скопируете очень длинную строку в argv [0], она может выйти за границы между param и env. В этом случае вы должны переместить область памяти argv и environment в другое пространство кучи, как показано ниже. Ниже приведен пример кода из открытого исходного кода Postgresql. ps_status.c)

char ** new_environ;
char ** new_argv;
char ** org_argv;
int     i;

new_argv = (char **) malloc((argc + 1) * sizeof(char *));
for (i = 0; i < argc; i++)
    new_argv[i] = strdup(argv[i]);
new_argv[argc] = NULL;
org_argv = argv;
argv = new_argv;

new_environ = (char **) malloc((i + 1) * sizeof(char *));
for (i = 0; environ[i] != NULL; i++)
    new_environ[i] = strdup(environ[i]);
new_environ[i] = NULL;
environ = new_environ;

Затем вы можете использовать getopt, getenv и т. Д. Они будут читать значения из вновь выделенной области памяти. Кроме того, если вы измените исходный параметр (org_argv [0]), вы можете манипулировать выходным именем вашего процесса в команде ps. (также сверху утилита htop) Смотри ниже.

$> ps -ef | grep my_proc
  dplee 10855 1 0 7월28 pts/2 00:00:16 my_proc i can manipulate this name
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...