2015-12-21 138 views
1

我在構建一個用圖形做各種事情的程序時遇到了這個問題。 我使用代碼塊在C中編寫代碼,如果我正常運行它(通過「構建和運行」)程序「工作」(它仍然沒有完成),但如果我嘗試通過調試器運行代碼,它會停止與Segmentation fault。這很奇怪。代碼正常運行,但調試給出了「分段錯誤」

下面是我的一些代碼提取爲了解決這個問題,遺憾的混亂:

的main.c

FILE *file; 
char *input = "input.txt"; 
file = fopen(input, "r"); // Open the file read-only 
if(file != NULL){ 
    G = parse(file, F);  // Parse the graph 
fclose(file); // Close the file 

Graph.h

struct TGraph { 
    void **adj; 
    int nodes_count; 
}; 

typedef struct TGraph *Graph; 
typedef enum GraphType {LIST, MATRIX} GraphType; 

typedef Graph (*INITGRAPH)(int); 
typedef void (*ADDADJ)(Graph, int, int, float); 
typedef void (*PRINT)(Graph); 

typedef struct funct{ 
    INITGRAPH init; 
    ADDADJ addEdge; 
    PRINT print; 
}FunctGraph; 

typedef struct AdjList{ //I need this in order to use the adj as a List 
    List *nodes; 
}AdjList; 

Graph.c

Graph initGraphList(int nodes_count){ 
    Graph G = malloc(sizeof(struct TGraph)); 
    ((AdjList *)(G->adj))->nodes = malloc(nodes_count * sizeof(List)); <<< PROBLEM HERE 
    G->nodes_count = nodes_count; 
    return G; 
} 

Gra phparser.c

Graph parse(FILE *file, FunctGraph *F){ 
    Graph G = NULL; 
    puts("Controllo numero di nodi..."); 
    if (!match(file, LPAR)){  // Check if number of nodes is present 
     syntax_error(errorsymb(LPAR), file); 
    }else{ 
     fseek(file,1,SEEK_CUR);  //Going over the LPAR 
     G = parse_init(file, F->init); //Initialize the Graph <<< PROBLEM HERE 
     if (G == NULL){ 
      fprintf(stderr, "Errore nell'allocazione del grafo\n"); 
      exit(1); 
     }else{ 
      if (!match(file, RPAR)) 
       syntax_error(errorsymb(RPAR), file); 
      else{     // If so parse the graph 
       fseek(file,1,SEEK_CUR); 
       printf("Rilevato grafo da %d nodi\n", G->nodes_count); 
       puts("Costruisco il grafo..."); 
       while(!match(file, DOT)){ 
        read_node(G, file, F->addEdge); 
       } 
      } 
     } 
    } 
    return G; // return the parsed Graph 
} 

int match(FILE *file, type et) 
{ 
    // Try to match symbol of expected type 'et' in file 
    // [returns 1 if successful, 0 otherwise] 
    char c; 
    type rp;      // Type of the symbol read 
    int res=0; 
    while(((c = fgetc(file)) == '\t') || (c == '\n') || (c == ' ')); // Skip intitial tabulation, newline and spaces 
    switch(c) {  // Determine the read symbol type 
     case ',': 
      rp = COMMA; break; 
     case '(': 
      rp = LPAR; break; 
     case ')': 
      rp = RPAR; break; 
     case '.': 
      rp = DOT; break; 
     case '-': 
      rp = MINUS; break; 
     case '>': 
      rp = ARROW; break; 
     case ';': 
      rp = SEMICOL; break; 
     default : 
      rp = NODEID; break; 
    } 
    ungetc(c,file); // Push the characters read back to the file 
    if (rp==et)  // The expexted type et and the read symbol type rp match 
     res = 1; 
    return res; 
} 

Graph parse_init(FILE *file, INITGRAPH init){ 
    unsigned int nodes; 
    fscanf(file, "%d", &nodes); 
    if(nodes >= INT_MAX) 
     syntax_error("Numero nodi troppo grande", file); 
    return init(nodes); // Initialize the graph 
} 

我認爲這應該是我們需要找到這個問題的所有代碼。 作爲我的標記代碼中的問題奠定了此行中:

((AdjList *)(G->adj))->nodes = malloc(nodes_count * sizeof(List)); 

這裏的調試器調用「段錯誤」,但我不明白爲什麼。 你有沒有任何想法,爲什麼代碼運行沒有調試器,而不是它,給出了這個錯誤? 在此先感謝您的幫助。

回答

2
Graph G = malloc(sizeof(struct TGraph)); 
((AdjList *)(G->adj))->nodes = malloc(nodes_count * sizeof(List)); 

您要爲G分配與malloc內存,但你永遠不與有效值initlize,所以提領G->adj會導致不確定的行爲。它似乎在發行版中起作用,但在調試版本中不起作用。

如果你正在使用Visual Studio,調試版本會初始化內存(我認爲0xFE什麼的,所以它會在你取消引用指針時崩潰,在發佈版本中這不會發生,所以它有一些隨機。地址,這顯然不會造成任何直接的問題,不知道是否也GCC做到這一點

你需要的是這樣的:

Graph G = malloc(sizeof(struct TGraph)); 
G->adj = malloc(whatever); 
G->node_count = 0; 
etc. 
((AdjList *)(G->adj))->nodes = malloc(nodes_count * sizeof(List)); 
+0

我試圖用你的建議分配是這樣的:「G->因爲想在稍後將其轉換爲'AdjList *' 調試器不會調用在那裏停下來,但是當試圖訪問列表的元素時,我收到另一個「分段錯誤」。 我認爲我的分配仍然存在問題。 – Aster

+0

@Baum 問題是我必須創建一個Graph結構,它可以支持列表和鄰接矩陣,爲了做到這一點,老師教我們使用'void *'指針,以便將該元素與任何一種方法。 有沒有辦法確保'G-> adj'是否指向一個有效的'AdjList'(或'AdjMatrix')對象? 當然,感謝你們雙方在你身邊幫助我。 – Aster

+0

你必須分配足夠的空間,以便爲結構中的較大結構保留所需數量的元素。爲了使它更易於維護,聯合可能是一個好主意,因爲那樣你可以根據需要在任何元素上添加元素而不需要投射它,而且sizeof也會給你正確的尺寸。 – Devolus

相關問題