strcmp引起的段错误

10

我正在以下方式中使用strcmp函数

  1. Passing char[] array names
  2. Passing pointers to string literals but, the second result in seg fault. even though i have confirmed that pointers point to correct string literals, i am confused as to why i am getting seg fault.. Here is the code:-

    #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)

3
在这个问题上投票“过于局限”毫无意义。这个问题可以说是https://dev59.com/zFzUa4cB1Zd3GeqP4IcL 的重复,因为真正的问题是“这个警告是什么意思?”但“过于局限”只是一种扭曲:没有帮助,也没有抓住重点。 - Flexo
2个回答

14

当您将同一变量作为两个不同参数传递给同一函数时,请勿使用--++

而不是printf("%d\n", strcmp(*(--args),*(++args)));

请使用

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

仍然不太易读(最好使用索引并检查 argc 的有效性),但至少你不会在同一序列点上更改值并多次评估它。


4
C语言不保证表达式的求值顺序,通常不是从左到右。在同一条语句中多次修改变量的行为是未定义的。 - C. K. Young
@Jimm,是的,但是你同时改变值并对它们进行评估,这是未定义的行为。 - littleadv
请问你能否友好地指引我一些gcc文档或官方来源,解释为什么在单个函数调用中无法访问同一个变量两次。请记住,++args和--args只是遍历内存地址,并不会修改任何内容。 - Jimm
6
它正在修改指针变量 args,而且在序列点之间你不能对它进行多次修改。 - R.. GitHub STOP HELPING ICE
2
感谢您让我了解了序列点(sequence point)。这是一个缺失的环节,使得我难以理解 littleadv 的评论。在维基百科上查看序列点(http://en.wikipedia.org/wiki/Sequence_point)后,它实际上在其参考文献中详细说明了该条款。 - Jimm
2
阅读comp.lang.c FAQ的第三部分,然后阅读其余部分。 - Keith Thompson

6
除了littleadv的帖子所说的之外,您的缓冲区还少一个字符(它没有留下任何空间给空终止符)。因此,您的strcpy会导致缓冲区溢出。

奇怪的是,尽管strcmp是一个不受限制的字符串函数,但上述代码在没有NULL字符的字符数组中运行良好。只有当我使用指针进行strcmp时,才会出现段错误。 - Jimm
1
@Jimm: 仍然是未定义行为,因为缓冲区溢出仍然发生了(它将写入一个空终止符; 只是会在您的缓冲区范围之外这样做)。在这种情况下,你很幸运缓冲区溢出没有更快地杀死你的程序。 - C. K. Young

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接