Как мне обрабатывать назначения массива символов argv?

StackOverflow https://stackoverflow.com/questions/1214251

  •  06-07-2019
  •  | 
  •  

Вопрос

Я нашел два способа передачи аргументов командной строки в массив символов:

int main (int argc, char **argv)
{
  const char *s1 = argv[0];
  char s2[256];
  strcpy(s2, argv[0]);

  printf("s1: %s\ns2: %s\n\n", s1, s2);
}

Скомпилированный с помощью компилятора IBM xlc в системе AIX Возвращает

[MyPrompt]> ./a.выход

s1:./a.выход

s2:./a.выход

Какая реализация (s1 или s2) является правильной?s1 хорош, потому что argv[0] может быть любой длины.s2 требует, чтобы длина argv[0] < 256 символов.

Я не понимаю, как / почему s1 должен работать.Я подумай правая часть s1 должна требоваться во время компиляции, но я подумай он генерируется во время выполнения.

Это было полезно?

Решение

Причина, по которой s1 работает, заключается в том, что тип argv[0] является указатель.Вы просто присваиваете адрес (не фактическое значение), который является безопасным.Вы не выполняете никакого распределения или приведения.

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

Другие советы

Если вы не хотите менять строку, то s1 будет работать.

Если вы хотите изменить строку, то вы можете сделать ее копию.Вам следует использовать более безопасные strnlen() и strncpy(), хотя, если ваша система их поддерживает.

Я думаю, что правая часть s1 должна требоваться во время компиляции, но я думаю, что она генерируется во время выполнения.

Нет, это требуется каждый раз, когда встречается оператор.Например:

void f() {
   int x = 1;
   ...
}

Целое число x будет инициализироваться равным 1 при каждом вызове функции, а не во время компиляции.

s2 обладает восхитительным свойством быть восприимчивым к переполнению буфера.

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

Если вы просто хотите сослаться на аргумент, не внося в него никаких изменений, то s1 является правильным.

Если вам нужно каким-либо образом изменить аргумент, то вам нужно сделать его копию, как в s2 например, но в s2 пример вам нужно явно проверить, не больше ли длина буфера, в который вы его копируете.Например, если вы принимаете аргумент типа filename.jpg в качестве входных данных и сохраняете filename.gif в качестве выходных данных, то вам нужно создать копию этого аргумента, поскольку вы будете изменять расширение с .jpg на .gif

Я бы выбрал s1, особенно для argv[n], где n > 0.Такие вещи, как s2, открывают вас для классических атак на переполнение буфера.По сути, пользователь может отформатировать аргумент длиной более 256 символов и перезаписать информацию в стеке, чтобы он мог запускать любой код, который он хочет.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top