Hackerrank 问题 (Post Transition) (C) 是什么导致了这个 seg 错误?

Hackerrank problem (Post Transition) (C) What's causing this seg fault?

我一直在尝试在 hackerrank 上解决这个问题 https://www.hackerrank.com/challenges/post-transition 但是当我尝试 运行 时,我的代码似乎产生了分段错误。 我已经检查了几十次,并将它与其他人的解决方案进行了比较,但我仍然无法理解我可能做错了什么。

这是我收到的错误消息:

  Reading symbols from Solution...done.

[New LWP 1602418]

[Thread debugging using libthread_db enabled]

Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Core was generated by `./Solution'.

Program terminated with signal SIGSEGV, Segmentation fault.

#0  send_all_acceptable_packages (source=source@entry=0x16eeec8, 
    source_office_index=0, target=target@entry=0x16eeee0, 
    target_office_index=<optimized out>) at Solution.c:58
58      int src_pk_count = (source->offices[source_office_index].packages_count);

这是我的代码

#include <stdlib.h>
#include <string.h>
#define MAX_STRING_LENGTH 6

struct package
{
    char* id;
    int weight;
};

typedef struct package package;

struct post_office
{
    int min_weight;
    int max_weight;
    package* packages;
    int packages_count;
};

typedef struct post_office post_office;

struct town
{
    char* name;
    post_office* offices;
    int offices_count;
};

typedef struct town town;



void print_all_packages(town t)
{
    printf("%s:\n",t.name);

    //offices loop
   for(int i=0;i<t.offices_count;i++)
   {
       printf("\t%i:\n",i);

       //packages loop
       for(int j=0;j<t.offices[i].packages_count;j++)
        {printf("\t\t%s\n", t.offices[i].packages[j].id);}
   }


}

void send_all_acceptable_packages
(town* source, int source_office_index, town* target, int target_office_index)

{

    int trg_pk_count = (target->offices[target_office_index].packages_count);
    int src_pk_count = (source->offices[source_office_index].packages_count);
   
    //weight condition
    
    int min_w = (target->offices[target_office_index].min_weight);
    int max_w = (target->offices[target_office_index].max_weight);
     

   for(int i=0;i<src_pk_count;i++)
    {


        int pckg_w = (source->offices[source_office_index].packages[i].weight);


        if ((pckg_w >= min_w) && (pckg_w <= max_w))
        {
            
         
            
             target->offices[target_office_index].packages = realloc                                 (target->offices[target_office_index].packages, sizeof(package)*                           (trg_pk_count+1));                 
             
            (target->offices[target_office_index].packages_count)++;
            (source->offices[source_office_index].packages_count)--;
             
             
                   
             target->offices[target_office_index].packages[(trg_pk_count)]=                           source->offices[source_office_index].packages[i];



             for(int x=0; x<(src_pk_count-1);x++)
             {
             source->offices[source_office_index].packages[i+x] = source->offices                     [source_office_index].packages[i+x+1] ;
             
             
             source->offices[source_office_index].packages= realloc(source->offices                   [source_office_index].packages, sizeof(package)*((source->offices                        [source_office_index].packages_count)));
             }
            

        }

            

    }
 
}


town town_with_most_packages(town* towns, int towns_count)
{
    //count
    int town_pkcount[towns_count];

    for(int i=0;i<towns_count;i++)
    {
        town_pkcount[i]=0;
        int sum=0;
        for(int j=0;j<towns[i].offices_count;j++)
        {

            sum+= towns[i].offices[j].packages_count;
        }


        town_pkcount[i]=sum;
    }

   //find max
   int max=-1 , max_index;
   for(int i=0; i<towns_count;i++)
   {
       if (town_pkcount[i]>max)
       {
           max = town_pkcount[i];
           max_index=i;
       }


   }


   return towns[max_index];


}

town* find_town(town* towns, int towns_count, char* name)
{
    int town_index=-1;
    for(int i=0; i<towns_count; i++)
    {
        if(strcmp(name,towns[i].name)==0)
        {town_index = i;}


        break;
    }



    return(&towns[town_index]);


}

int main()
{
    int towns_count;
    scanf("%d", &towns_count);
    town* towns = malloc(sizeof(town)*towns_count);
    for (int i = 0; i < towns_count; i++) {
        towns[i].name = malloc(sizeof(char) * MAX_STRING_LENGTH);
        scanf("%s", towns[i].name);
        scanf("%d", &towns[i].offices_count);
        towns[i].offices = malloc(sizeof(post_office)*towns[i].offices_count);
        for (int j = 0; j < towns[i].offices_count; j++) {
            scanf("%d%d%d", &towns[i].offices[j].packages_count, &towns[i].offices[j].min_weight, &towns[i].offices[j].max_weight);
            towns[i].offices[j].packages = malloc(sizeof(package)*towns[i].offices[j].packages_count);
            for (int k = 0; k < towns[i].offices[j].packages_count; k++) {
                towns[i].offices[j].packages[k].id = malloc(sizeof(char) * MAX_STRING_LENGTH);
                scanf("%s", towns[i].offices[j].packages[k].id);
                scanf("%d", &towns[i].offices[j].packages[k].weight);
            }
        }
    }
    int queries;
    scanf("%d", &queries);
    char town_name[MAX_STRING_LENGTH];
    while (queries--) {
        int type;
        scanf("%d", &type);
        switch (type) {
        case 1:
            scanf("%s", town_name);
            town* t = find_town(towns, towns_count, town_name);
            print_all_packages(*t);
            break;
        case 2:
            scanf("%s", town_name);
            town* source = find_town(towns, towns_count, town_name);
            int source_index;
            scanf("%d", &source_index);
            scanf("%s", town_name);
            town* target = find_town(towns, towns_count, town_name);
            int target_index;
            scanf("%d", &target_index);
            send_all_acceptable_packages(source, source_index, target, target_index);
            break;
        case 3:
            printf("Town with the most number of packages is %s\n", town_with_most_packages(towns, towns_count).name);
            break;
        }
    }
    return 0;
}

请记住,结构和主要功能已经预先编写

段错误似乎与send_all_acceptable_packages函数有关

还要记住,段错误发生在输入这行输入之后 2 B 0 A 1 这会触发 main

中的案例 2
  case 2:
            scanf("%s", town_name);
            town* source = find_town(towns, towns_count, town_name);
            int source_index;
            scanf("%d", &source_index);
            scanf("%s", town_name);
            town* target = find_town(towns, towns_count, town_name);
            int target_index;
            scanf("%d", &target_index);
            send_all_acceptable_packages(source, source_index, target, target_index);
            break;

您可以在其中看到 find_town 函数的 return 值用作 [=45= 的输入] 使我相信故障出在这两个函数之一的函数

请帮我找出这里的问题,非常感谢你的意见。

下面的循环永远不会迭代:

town* find_town(town* towns, int towns_count, char* name)
{
    int town_index=-1;
    int i = 0;
    
    for(i=0; i < towns_count; i++)<-warning points here (i++)
    {
        if(strcmp(name,towns[i].name)==0)
        { town_index = i;}   
        break;<- cause of warning
    }
    return(&towns[town_index]);
}

我从我的调试器中看到以下警告:

150, 31 warning: will never be executed

break 语句保证循环永远不会迭代。

您可能打算将其放在 if() 语句中

town* find_town(town* towns, int towns_count, char* name)
{
    int town_index=-1;
    int i = 0;
    
    for(i=0; i < towns_count; i++)
    {
        if(strcmp(name,towns[i].name)==0)
        { 
            town_index = i;
            break;
        }   
        
    }
    return(&towns[town_index]);
}

要查看的其他一些项目:

  • int main(void);Cmain 函数的最小原型(不是 int main()
  • 代码不检查应始终检查的 returns 函数(例如 scanf())。
  • 最好限制对 scanf() 的调用的输入长度以防止溢出,即对于 #define MAX_STRING_LENGTH 6,用户只能使用一些非常短的名称,但如果输入城市因为“达拉斯”scanf("%s", towns[i].name); 程序会溢出。写成 scanf("%(MAX_STRING_LENGTH-1)s", towns[i].name); 来限制用户输入的合法长度。
  • 建议将 #define MAX_STRING_LENGTH 6 更改为更现实的值。
  • 内存泄漏。代码释放 none 创建的内存。每次调用 malloc()
  • 时调用一次 free()
  • 在每个 scanf() 之前使用 printf() 列出用户输入的说明。 (例如:printf("enter town name\n");