返回指针时出现分段错误

Posted

技术标签:

【中文标题】返回指针时出现分段错误【英文标题】:Segmentation fault when returning a pointer 【发布时间】:2013-10-29 02:55:56 【问题描述】:

我正在尝试用 C 语言编写一个可以获取环境变量的代码,然后使用 strstr 从该结果中搜索特定的单词。我正在使用 UBUNTU 操作系统和 gcc 编译器。这是我编写的代码。评论是我预期会发生的。

#include <stdio.h>
#include <string.h>
#include <unistd.h>

extern char **environ;
extern char **tmp;
extern char **tmp2;

char *search_string(char *tmp,int x)

      char string[]="ABC";          //I'm looking for ABC in the environment variable
      char *pointer;
      pointer=strstr(tmp,string);   //pointer will point to the result of strstr
      if(pointer != NULL)
             printf("%s ,",tmp);
              printf("data found : %s \n",pointer);
       else  
              //hope to do something
      
      return (pointer);


int main(char *tmp2)

      int x = 0;
      for(x=0;environ[x]!='\0';x++)   //I'm expecting it to keep looping until finish
      tmp2=search_string(environ[x],x); //tmp2 will point to the function return value
      printf("%s\n",tmp2);             //print the return value
        //If the search_string return NULL, does it consider string or something else?
      return 0;

运行代码后,由于核心转储而崩溃。这是输出。

ABC=/tmp ,data found : ABC=/tmp 
ABC=/tmp
Segmentation fault (core dumped)

据我所知,它只能执行 1 次 search_string。然后它崩溃了。然后我使用 gdb 找出它实际上在哪一行崩溃,结果如下:

Starting program: /home/fikrie/a.out 
ABC=/tmp ,data found : ABC=/tmp 
ABC=/tmp

Program received signal SIGSEGV, Segmentation fault.
__strlen_ia32 () at ../sysdeps/i386/i686/multiarch/../../i586/strlen.S:99
99  ../sysdeps/i386/i686/multiarch/../../i586/strlen.S: No such file or directory.

我从调试中不明白的是,由于 SEGV 信号,它正在接收错误。有人可以指点我如何解决这个问题吗?是不是因为 search_string 返回的是 NULL 值?

【问题讨论】:

environ[x] 包含什么? main 中的参数列表是非标准的。 environ s 指向 char 的指针-也许问题就在那里。 我很惊讶你可以循环 environ[x] 直到你找到一个 NULL - 请注意你应该真正测试 NULL 而不是 '\0' 因为这是一个指针...... @Acme environ[x] 包含可以获取环境变量的指针。通过打印 environ[x],我应该在 /etc/profile 中获得环境变量。 @Floris 我可以循环,因为据我所知,它是一个指针数组,将在收集所有数据后结束。据我所知,数组将以'/0'结尾对吗? 一个 string 将以 '\0' 结尾,但是没有理由为什么 pointers 数组的最后一个元素应该包含 NULL .尽管这样做是件好事——这意味着您不必显式传递数组的大小。但我不知道 C 标准的任何部分说它应该是这样。 【参考方案1】:

问题是如果search_string() 没有找到字符串,它会返回NULL。然后将 NULL 传递给 printf(),这会崩溃。

main() 中,您需要类似:

if (tmp2)
    printf("%s\n", tmp2);

另外,tmp2 变量的类型应该是 char *,而不是 char **。并且没有理由不将其声明为 main() 本地。

【讨论】:

是的!你是完全正确的。它核心转储,因为 search_string 在第二次搜索后返回 NULL,如果它没有找到我指定的单词,这是 strstr 的输出。因此,printf 无法打印 NULL 结果。 你的建议很好。它确实有效。在代码中应用 'if(tmp2)' 时,它将在 environ[x] 中搜索 1 次。但就我而言,我想检查整个环境变量,这就是我使用 'for(x=0;environ[x]!='\0';x++)' 进行搜索的原因。如果“strstr”没有找到任何结果,我只需要知道如何避免返回“NULL”。我的方法错了吗? @MohdFikrie:添加if (tmp2) 确实意味着它仍在搜索整个环境-只是它只会在找到目标字符串时执行printf() .要查看这一点,请创建多个包含搜索字符串的环境变量(例如 ABCx=1 ABCy=1)。 我已经尝试过您的建议,但它的行为不正常。我添加了“ABC=/home”、“ABCx=/etc”和“ABCy=/home/fikrie”。通过使用命令'env'。我发现'ABC = / home'在顶部,其他2在底部。当我运行代码时,它只找到'ABC / home'而不是其他2。我假设它会停止搜索如果它在环境中找到'NULL',即使它的下部仍然有'ABC' .听起来对吗? @MohdFikrie:它不会停止搜索,因为您的代码表示无论是否找到匹配项,都将继续搜索,直到到达环境结束。您可能没有导出额外的环境变量。【参考方案2】:

对主循环的一个非常简单的更改可以防止程序崩溃:

int main(char *tmp2)

      int x = 0;
      for(x=0;environ[x]!='\0';x++)   //I'm expecting it to keep looping until finish
      tmp2=search_string(environ[x],x); //tmp2 will point to the function return value
// >>>>> change these next two lines:
      if(tmp2 != NULL) printf("%s\n",tmp2);             //print the return value
      else printf("%s does not contain ABC\n", environ[x]);
// <<<<< end of change
        //If the search_string return NULL, does it consider string or something else?
      return 0;

请注意,如果您只期望一个匹配项,您可以在打印匹配项时添加 break;。上面的代码打印出所有的环境变量——你可以看到它并没有停止...

【讨论】:

以上是关于返回指针时出现分段错误的主要内容,如果未能解决你的问题,请参考以下文章

尝试从方法返回指向对象的指针时出现分段错误

返回指针时出现分段错误

在 C++ 中使用指针的数组:访问返回的数组时出现分段错误

启动线程导致指针初始化时出现分段错误

在指针迭代中使用 for 循环时出现分段错误

删除时出现分段错误