【问题标题】:segmentation fault in mallocmalloc中的分段错误
【发布时间】:2014-02-23 14:15:06
【问题描述】:

我编写了以下程序,每次尝试运行它时都会遇到分段错误。我认为问题出在第 149 行的数组子集的 malloc 上。我尝试使用 gdb 对其进行调试,但它说函数 find 存在问题,这根本没有任何意义。如果有人遇到过类似的问题,请帮忙。非常感谢。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <inttypes.h>

long int N;

// a structure to represent a weighted edge in graph
struct Edge
{
    long int src, dest ;
    long int weight;
 };

 // a structure to represent a connected, undirected and weighted graph
 struct Graph
 {
 struct Edge* edge;
  };


  // A structure to represent a subset for union-find
  struct subset
  {
        long int parent;
        long int rank;
        long long int vertex;
   };


    // A utility function to find set of an element i
    long int find(struct subset subsets[], long int i)
    {
        // find the root and make root as parent of i (path compression)
       if (subsets[i].parent != i)
       subsets[i].parent = find(subsets, subsets[i].parent);

       return subsets[i].parent;
     } 


     // Union of two sets of x and y
     // (uses union by rank)
     void Union(struct subset subsets[],long int x,long int y)
     {
        long int xroot = find(subsets, x);
        long int yroot = find(subsets, y);
            // Attach smaller rank tree under root of high rank tree
        // (Union by Rank)
        if (subsets[xroot].rank < subsets[yroot].rank){
             subsets[xroot].parent = yroot;
             subsets[yroot].vertex += subsets[xroot].vertex;
        }
        else if (subsets[xroot].rank > subsets[yroot].rank){
             subsets[yroot].parent = xroot;
             subsets[xroot].vertex += subsets[yroot].vertex;
        }
        // If ranks are same, then make one as root and increment
        // its rank by one
        else
        {
        subsets[yroot].parent = xroot;
        subsets[xroot].rank++;
            subsets[xroot].vertex += subsets[yroot].vertex;
        }
       }

     // Compare two edges according to their weights.
     // Used in qsort() for sorting an array of edges
     int comp(const void* a, const void* b)
     {
        struct Edge* a1 = (struct Edge*)a;
        struct Edge* b1 = (struct Edge*)b;
        return (a1->weight - b1->weight);
      }




      int main(int argc, char *argv[])
      {
        int j;
        long int i;
        long int n1, n2, w;
        long long int sum=0;
        FILE *f = fopen(argv[1], "r");

        if (!f) {
            exit(EXIT_FAILURE);
        }
        fscanf(f, "%ld", &N);

        struct Graph* graph = (struct Graph*) malloc( sizeof(struct Graph) );

        graph->edge = (struct Edge*) malloc( N * sizeof( struct Edge ) );
        for (i = 0; i < N-1; i++) {
            fscanf(f, "%ld", &n1);
            fscanf(f, "%ld", &n2);
            fscanf(f, "%ld", &w);

            graph->edge[i].src = n1;
            graph->edge[i].dest = n2;
            graph->edge[i].weight = w;
        }

        long int x,y;
        struct Edge next_edge ;

        qsort(graph->edge, N-1, sizeof(graph->edge[0]), comp);

            /*
        for (i = 0; i < N -1 ; i++)
        {
            printf("%ld\t %ld\t %ld\n", graph->edge[i].src, graph->edge[i].dest,             graph->edge[i].weight); 
        }
         */
        // Allocate memory for creating V subsets
        struct subset *subsets = (struct subset*) malloc( N * sizeof(struct subset) );
        // Create V subsets with single elements
        for (j = 0 ; j < N ; j++)
        {
                subsets[j].parent = 0;
            subsets[j].rank = 0;
            subsets[j].vertex = 1 ; 
        }

        i = 0; 
        while (i < N-1)
        {
            next_edge = graph->edge[i--];
            x = find(subsets, next_edge.src);
            y = find(subsets, next_edge.dest);
            if (x != y){
                      sum += graph->edge[i].weight + ( ( graph->edge[i].weight +1 ) * (subsets[x].vertex*subsets[y].vertex-1));
                Union(subsets, x, y);
            }
        }

        printf("%lld\n", sum);

        return 0 ;
       } 

附:该程序的目的是,给定一个 MST,以给定的 MST 是它唯一的 MST 的方式计算一棵完整树的权重。

【问题讨论】:

  • 你能把代码缩小到麻烦的部分吗?您可以通过在调试器中运行程序来做到这一点,它会在崩溃发生时停止并让您检查调用堆栈(至少请在您的问题中包含它),甚至可以向上走调用堆栈,让您检查值的变量。既然你提到了分段错误,你可能想了解一下the GNU Debugger and read its online manual

标签: c segmentation-fault malloc


【解决方案1】:

可能的原因是他的循环:

i = 0; 
while (i < N-1)
{
    next_edge = graph->edge[i--];
    ...
}

这里你从索引零开始,然后减少它。因此,当您稍后在循环中使用i 作为索引时,它将具有值-1,并且您将索引超出分配内存的范围,从而导致未定义的行为。只要i 为负数,循环本身也可以运行,直到它下溢成为最大签名long 值(因此您将循环超过20 亿次)。

【讨论】:

  • 你说的太对了。这是一个粗心的错误,但通常问题是这样的。另外,我应该按字段进行此初始化“next_edge = graph->edge[i--]”。现在程序并不完全正确,但至少它运行了!谢谢!
猜你喜欢
  • 2021-11-17
  • 1970-01-01
  • 2014-03-29
  • 2015-01-29
  • 1970-01-01
  • 2011-02-13
  • 1970-01-01
  • 1970-01-01
  • 2019-02-01
相关资源
最近更新 更多