【问题标题】:C language, where is the segmentation fault?C语言,分段错误在哪里?
【发布时间】:2013-04-15 01:18:09
【问题描述】:

这是我得到分段错误的函数

void searchcity()
{
    struct city *ptr=citylist;
    printf("Which city would you like me to search?: ");
    scanf("%s",searchedcity);
    //  printf("%s",searchedcity);
    while(ptr)
    {
        if(!strcmp(searchedcity,ptr->name))
            printf("name= %s, statecode = %s,population = %s,region = %s,zipcode =     %s\n",ptr->name,ptr->statecode,ptr->population,ptr->region,ptr->zipcode);
        else
            printf("sorry, couldnt find that city");
        ptr=ptr->next;
    }   
}

不确定是什么原因造成的。

【问题讨论】:

  • 可能有很多原因,但没有更多代码就很难说出来
  • 这里没有足够的代码来调试这个。
  • 在函数中是否有任何原因导致它?
  • @alex 我们需要查看更多代码才能弄清楚这一点,而无需猜测。
  • 你有没有用调试器检查过这个问题,看看是否有任何指针是NULL,但不应该是?

标签: c function segmentation-fault strcmp


【解决方案1】:

根据该代码 (a),您至少需要检查以下内容:

  • searchedcity 有足够的空间用于输入 (b)
  • citylist 链表中的所有字符串均已正确构造(以空值结尾)。
  • 结构中的所有字段都是实际上是字符数组(或等效指针)而不是整数(例如人口)。
  • 列表本身已正确构建(没有悬空或无效指针)。

您确实有一个其他问题,但与段错误无关。

您的代码将为列表中与您的城市不匹配的每个节点打印"sorry, couldnt find that city",因此,如果您有New YorkMoscowLondon,然后您查看对于London,您将在找到该消息之前将其打印两次。

一个更好的解决方案(许多变体之一)是这样的:

struct city *ptr = citylist;
while (ptr != NULL)
  if (strcmp (searchedcity, ptr->name) == 0)
    break;

if (ptr == NULL)
  printf ("Sorry, couldnt find that city.\n");
else
  printf ("%s, state = %s, pop = %s,r egion = %s, zip = %s\n",
    ptr->name, ptr->statecode, ptr->population, ptr->region, ptr->zipcode);

这样,循环负责找到正确的指针或将其设置为 NULL。 之后循环是决定应该打印什么的正确时间。


(a) 除了危险的scanf 之外,该代码本身似乎还可以,但它确实依赖于很多其他未显示的内容。

(b) 事实上,scanf 与无限 %s 是代码中的一个严重漏洞,很容易导致缓冲区溢出。有关详细信息和解决方案,请参阅here。在任何情况下,scanf("%s") 都不是扫描带有空格的字符串的好方法,因为像Los Angeles 这样的东西最终会变成Los :-)

【讨论】:

    【解决方案2】:

    下面的代码有效,我做了一些小的改动,你可以通过它来完成。您犯的几个小错误是您的 ptr->next 由于缺少括号而从未执行。其余的我写在代码里。

    谢谢,希望我们能帮上忙。

    #include <stdio.h>
    struct city {
        char name[100];
        char  statecode[100];
        char  population[100];
        char region[100];
        char zipcode[100];
        struct city* next;
    };
    
    int main() // this is your searchcity function
    {
        char searchedcity[100]; // make sure you initialize this. YOu haven't done it in the code you gave us.
            // Assume citylist is in your main function or initialized as a global var
            // I initialized it here for simplicity
        struct city* citylist = (struct city*) malloc(sizeof( struct city));
        strcpy(citylist->statecode,"statecode");
        strcpy(citylist->population,"population");
        strcpy(citylist->region,"region");
        strcpy(citylist->zipcode,"zipcode");
        citylist->next = NULL;
    //end of citylist
        struct city *ptr = citylist;
        printf("Which city would you like me to search?: ");
        scanf("%s",searchedcity);
    //  printf("%s",searchedcity);
        while(ptr)  {
            printf("while \n");
            if(!strcmp(searchedcity,ptr->name)){
                   printf("name= %s, statecode = %s,population = %s,region = %s,zipcode =     %s\n",ptr->name,ptr->statecode,ptr->population,ptr->region,ptr->zipcode);
            }else{
                    printf("sorry, couldnt find that city");
                    ptr=ptr->next;
            }
        }
        return 0;
    }
    

    【讨论】:

    • 请解释ptr-&gt;next在原始代码中没有被执行的争论。将它移动到大括号内对循环没有影响,因为如果它为 NULL,它就不会在循环中。
    • @paxdiablo 哦,效果不错……找到城市时会产生无限循环。循环是错误的,但这肯定不是解决办法。