Segfault с помощью strcmp

Я использую strcmp следующими способами

  1. Передача имен массивов char[]
  2. Передача указателей на строковые литералы, но второй результат приводит к ошибке seg. хотя я подтвердил, что указатели указывают на правильные строковые литералы, я не понимаю, почему я получаю ошибку seg. Вот код: -

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main(int argc, char const *args[])
    {
      char firstName[strlen(*++args)];
      strcpy(firstName, *args);
      char lastName[strlen(*++args)];
      strcpy(lastName, *args);
      printf("%s\t%s\n", firstName, lastName);
    
      printf("%d\n", strcmp(firstName, lastName));// this works
    
      printf("%d\n", strcmp(*(--args),*(++args)));//this gives me a seg fault
    
      return EXIT_SUCCESS;
    }
    

Я сохраняю его как str.c, и когда я его компилирую, сначала я получаю следующее предупреждение:

[Neutron@Discovery examples]$ gcc -Wall str.c -o str

str.c: In function ‘main’:
str.c:15: warning: operation on ‘args’ may be undefined

наконец, запустив его, выдает ошибку сегмента, как показано ниже.

[Neutron@Discovery examples]$ ./str Jimmy Neutron


Jimmy   Neutron

-4

Segmentation fault (core dumped)

person Jimm    schedule 10.06.2011    source источник
comment
Слишком локализованное голосование по этому поводу вообще не имеет смысла. Возможно, это дубликат stackoverflow.com/questions/7877258/, поскольку реальный вопрос заключается в том, что означает это предупреждение? но слишком локализовано просто извращенно: бесполезно и упускает суть.   -  person Flexo    schedule 16.03.2012


Ответы (2)


Не используйте -- и ++, когда вы передаете одну и ту же переменную одной и той же функции дважды как два разных параметра.

Вместо printf("%d\n", strcmp(*(--args),*(++args)));

do

char *first = *(--args);
char *second = *(++args);
printf("%d\n", strcmp(first,second));

Все еще не очень читабельно (лучше использовать индексы и проверять argc на достоверность), но, по крайней мере, вы не меняете значение и не оцениваете его несколько раз в одной и той же точке последовательности.

person littleadv    schedule 10.06.2011
comment
@Jimm: C не гарантирует никакого порядка оценки. Обычно это не слева направо. Изменение переменной более одного раза в одном операторе является поведением undefined. - person Chris Jester-Young; 10.06.2011
comment
@ Джимм, да, но вы одновременно меняете значения и оцениваете их, это неопределенное поведение. - person littleadv; 10.06.2011
comment
Не могли бы вы быть достаточно любезны, чтобы указать мне на какую-нибудь документацию gcc или какой-либо официальный источник, который объясняет, почему я не могу получить доступ к одной и той же переменной дважды в одном вызове функции. Пожалуйста, имейте в виду, что ++args и --args просто перебирают адреса памяти. Он ничего не изменяет. - person Jimm; 10.06.2011
comment
Он изменяет переменную указателя args, и вы не можете изменять ее более одного раза между точками последовательности. - person R.. GitHub STOP HELPING ICE; 10.06.2011
comment
Спасибо, что донесли до меня точку последовательности. Это было недостающее звено, из-за которого мне было трудно понять комментарии littleadv. После поиска в Википедии точек последовательности, en.wikipedia.org/wiki/Sequence_point, на самом деле сообщает точное предложение в его ссылках - person Jimm; 10.06.2011
comment
Прочитайте раздел 3 часто задаваемых вопросов о comp.lang.c. Затем прочтите остальную часть. - person Keith Thompson; 14.03.2012

В дополнение к тому, что говорится в сообщении littleadv, ваши буферы на один символ короче (не осталось места для нулевого терминатора). Таким образом, ваш strcpy вызывает переполнение буфера.

person Chris Jester-Young    schedule 10.06.2011
comment
Странно, несмотря на то, что strcmp является строковой функцией без ограничений, приведенная выше функция отлично работает с символьными массивами БЕЗ NULL-символов. Только когда я делаю strcmp с указателями, я получаю ошибку seg. - person Jimm; 10.06.2011
comment
@Jimm: Это все еще неопределенное поведение, поскольку переполнение буфера все еще происходит (он будет писать нулевой терминатор; он просто сделает это за пределами границ вашего буфера). В этом случае вам повезло, что переполнение буфера не убило вашу программу раньше. - person Chris Jester-Young; 10.06.2011