【问题标题】:Code compiles but gives segmentationfault when run with game board代码可以编译,但在使用游戏板运行时会出现分段错误
【发布时间】:2014-12-10 21:07:01
【问题描述】:

问题

我的最终目标是为这样的游戏打开一个游戏板:http://www.rci-jeux.com/jeux/labychiffres/laby.swf,然后将其作为大学作业来玩(我在国外,不能总是听从讲师所说的一切)。

我的问题是我认为pile.c - 下面的第三块代码。我已经用 gdb 确定了这一点(我对此非常缺乏经验):(我已经从代码中删除了 cmets,因此行号不正确 - 但它仍然在它所指的行上显示 DEBUGGING PROBLEM)。

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400ee6 in afficher_pile (pile=...) at pile.c:48
48            afficher(P_elt->valeur);//########DEBUGGING PROBLEM

在我看来,这就像非常简单的 afficher (print) 函数所指的是不应该的东西,但我基本上(正如讲师建议的那样)编辑了他提供给我们的一些简单的字符串操作函数,其中类型或结构是一个字符和一个指向下一个字符的指针,并且链的末端(如果我理解正确的话)有一个 NULL 指针。

我对编程很陌生,但我们对结构有相当广泛的指导,所以它们应该是适当和正确的(pile.c 函数也应该如此)。

我尝试过的

最初我以为我错误地传递了元素的valeur 部分,所以我尝试以各种方式更改afficher(P_elt->valeur);

afficher(P_elt.valeur);

afficher(*P_elt.valeur);

afficher(&P_elt.valeur);

这三个不编译说member valeur in something not a struct or union

afficher(&P_elt->valeur);编译错误:expected ‘POSITION’ but argument is of type ‘struct POSITION *

afficher(*P_elt->valeur);编译错误:invalid type argument of unary ‘*’ (have ‘POSITION’)

我一直在寻找这样的问题:C - Segfault when accessing member of non null pointer struct

C segmentation fault when trying to implement LinkedList(我对此抱有希望,但我不认为这是我的错误,我确信我的代码确实使用 NULL 指针初始化了结构。)

基本上我还没有找到其他可以尝试的方法,并且希望在最后一次有机会与讲师一起讨论之前取得更大的进步。

代码如下

1.proj.h 头文件(注意,其中包含一些我尚未编写的函数的原型。)

2.proj.c将是主文件,进展不大。

3.pile.c 包含由 gdb 突出显示的导致分段错误的代码,还用于操作最终玩家和求解器将用于解决游戏的位置列表。

4.allocate_plat.c 这会读取一个游戏文件(程序之前会从游戏文件加载并显示网格。)这可能是问题所在,因为这里使用游戏板中的值初始化了 PILE 结构。

5.makefile 可能没必要,但之前发现有问题。

6.plateau1.txt 这似乎正确地复制到了文本编辑器中(至少从预览开始 - 不应该有尾随空格(尽管我不知道这是否重要)。

1.proj.h

#pragma once

typedef struct position_st{
    int indl;//indice of ligne
    int indc;//indice of colonne
    }POSITION;

typedef struct element_st{
    POSITION valeur;
    struct element_st *P_suivant;
    }ELEMENT;

typedef struct pile_st{
    ELEMENT * P_sommet;
    }PILE;

//##########PLATEAU STRUCTURE DEFINITION##############
typedef struct plat_st{
//########## INFORMATION INCLUDED IN AND READ FROM THE GAME FILE
    int nl;//number of lignes in grille
    int nc;//number of colonnes in grille
    POSITION dep;//position du depart: dep.indl and dep.indc
    POSITION arr;//position d'arrive: arr.indl and arr.indc
    int longdem;//longueur demandee
    int sumdem;//totale demandee
    int ** grille;//Playing grid done by analogy with matrix
//#######INFORMATION TO DO WITH THE CURRENT GAME ########
    int longcur;//longueur courant
    int sumcur;//totale courant
    PILE chemin;//The path
    }PLATEAU;


//########## FUNCTION PROTOTYPES and source files ###############
//allocate_plat.c allocate_plat.c allocate_plat.c allocate_plat.c 
//allouer allocates the variables for the game
int allouer(PLATEAU *, int, int, int, int, int, int, int, int);
//lire reads a game from a file
int lire(char *, PLATEAU *);
//affiche prints grille
void affiche_grille(PLATEAU);

//pile.c pile.c pile.c pile.c pile.c pile.c pile.c pile.c pile.c 
//FONCTIONS DE PILE ETC
int afficher (POSITION); prints position
ELEMENT* nouvel_element (POSITION);
void initialiser_pile(PILE *);
int est_vide (PILE);
int afficher_pile (PILE);
int longueur_pile (PILE);
ELEMENT* empiler(PILE *, ELEMENT *);
ELEMENT* depiler (PILE *);
POSITION lire_sommet (PILE *);

//grille.c grille.c grille.c grille.c grille.c grille.c grille.c 
// GRILLE.C FONCTIONS DE GESTION DE LA GRILLE
int lire_valeur_a(PLATEAU *,POSITION *);
int lire_passage_a(POSITION);
int lire_direction_a(POSITION);
int ecrire_passage_a(POSITION);
int ecrire_direction_a(POSITION);

2.proj.c

#include <stdio.h>
#include <stdlib.h>
#include "proj.h"

int main(int argc, char* argv[]){
    int choix, choix2, succes;
    PLATEAU jeu;
    ELEMENT *P_elt;//////////// ELEMENT HERE *P_elt

    if (argc == 1){
        printf("Erreur : argument manquant !\n");
        return EXIT_FAILURE;
    }

    char *nom_fichier = argv[1];
    succes=lire(nom_fichier, &jeu);

    if (!succes){
        printf("Erreur lors de la lecture du fichier !\n");
        return EXIT_FAILURE;
    }

    afficher_pile(jeu.chemin);

    if (est_vide(jeu.chemin) == 0){
        printf("Chemin vide\n");
    }
    printf("%d. this is 0 if chemin not empty",est_vide(jeu.chemin));
    affiche_grille(jeu);
    afficher_pile(jeu.chemin);
    if(!est_vide(jeu.chemin)) afficher(lire_sommet(&jeu.chemin));
    printf("\n");
    return 0;
}

3.pile.c

#include <stdio.h>
#include <stdlib.h>
#include "proj.h"

////////// AFFICHER POSITION ////////////////////////////
int afficher(POSITION v){
    printf("\t%d %d", v.indl,v.indc);
}

///////// NOUVEL_ELEMENT /////////////////////////////
ELEMENT *nouvel_element (POSITION nouvelle_valeur){
    ELEMENT *P_elt;
    P_elt =(ELEMENT*) malloc(sizeof(ELEMENT));

    if(P_elt ) {
        P_elt->valeur= nouvelle_valeur;
        P_elt->P_suivant=NULL;
    }
    return P_elt;
}

/////////////////////////////////////////////////////
void initialiser_pile(PILE *P_pile){
    P_pile->P_sommet=NULL;
}

////////////EST VIDE /////////////////////////////////////////
int est_vide (PILE pile){
   return pile.P_sommet == NULL;//i.e. true (non-zero) if P_sommet is NULL
}

////////// AFFICHER PILE PRINT PATH //////////////////
int afficher_pile (PILE pile){
   ELEMENT *P_elt; 
   int l=0;
   for(P_elt= pile.P_sommet ; P_elt!=NULL ; P_elt=P_elt->P_suivant, l++ )
      afficher(P_elt->valeur);//######## DEBUGGING PROBLEM #################
   return l;
}

/////////// LENGTH OF PATH //////////////////////////
int longueur_pile (PILE pile){
   ELEMENT *P_elt; 
   int l=0;
   for(P_elt= pile.P_sommet ; P_elt!=NULL ; P_elt=P_elt->P_suivant )
      l++;

   return l;
}

///////////EMPILER ADD ELEMENT TO PATH //////////////
ELEMENT* empiler(PILE *P_pile, ELEMENT *P_elt_ajoute){
   P_elt_ajoute ->P_suivant = P_pile->P_sommet; /*on chaine P_elt_ajoute a la suite */
   P_pile->P_sommet = P_elt_ajoute;             /*on chaine  la sommet a P_elt_ajoute */

   return P_elt_ajoute;
}
/////////DEPILER REMOVE ELEMENT FROM PATH///////////
ELEMENT* depiler (PILE *P_pile){
   ELEMENT *P_elt_supprime;
   /* Si la pile est vide */
   if (est_vide(*P_pile))
      return NULL;
   /* Si la pile n'est pas vide */
   P_elt_supprime=P_pile->P_sommet ;
   P_pile->P_sommet = P_elt_supprime->P_suivant; /*on chaine la sommet a la suite */
   P_elt_supprime->P_suivant=NULL;   /* on supprime le chainage de P_elt_supprime */

   return P_elt_supprime;
}
//*
/////////////// LIRE SOMMET ////////////////////////
POSITION lire_sommet (PILE *P_pile){
    ELEMENT *P_elt; 
//      if (est_vide(*P_pile)) 
//  return NULL;      //sortie fonction
    for(P_elt = P_pile->P_sommet; P_elt->P_suivant != NULL; P_elt = P_elt->P_suivant);
   return P_elt->valeur;
}

4.allocate_plat.c N.B.中间包含一些重复的 fscanfs,我很确定它们可以工作。

#include <stdio.h> 
#include <stdlib.h>
#include "proj.h"

int allouer(PLATEAU *PLAT, int nl, int nc, int ldep, int cdep, int larr, int carr, int longdem, int sumdem){
    int i,succes;
    PLAT->grille = (int**)calloc(nl,sizeof(int*));
    PLAT->nl = nl;
    PLAT->nc = nc;
    PLAT->longdem = longdem;
    PLAT->sumdem = sumdem;
    PLAT->dep.indl = ldep;
    PLAT->dep.indc = cdep;
    PLAT->arr.indl = larr;
    PLAT->arr.indc = carr;
    succes = (PLAT->grille != NULL);
    for (i=0; succes && i<nl;i++){
    PLAT->grille[i]=(int*)calloc(nc,sizeof(int));
    succes = (PLAT->grille[i] != NULL);
    }
    return succes;
}
int lire(char *nom_fichier, PLATEAU *PLAT){
    int i,j,succes, c;
    FILE *fp;

    fp = fopen(nom_fichier, "rt");
    if(fp==NULL) {
        printf("Erreur d'ouverture du fichier\n");
        return 0;
    }
    c = fscanf(fp,"%d %d",&PLAT->nl,&PLAT->nc);//Read first line
    if( c != 2){
        printf("Erreur de format de fichier\n");
        fclose(fp);
        return 0;
    }
    c = fscanf(fp,"%d %d",&i,&j);//Read second line
    PLAT->dep.indl=i-1;
    PLAT->dep.indc=j-1;
    if( c != 2){
        printf("Erreur de format de fichier\n");
        fclose(fp);
        return 0;
    }
    c = fscanf(fp,"%d %d",&i,&j);//Read third line
    PLAT->arr.indl=i-1;
    PLAT->arr.indc=j-1;
    if( c != 2){
        printf("Erreur de format de fichier\n");
        fclose(fp);
        return 0;
    }
    c = fscanf(fp,"%d %d",&PLAT->longdem,&PLAT->sumdem);//Read fourth line
    if( c != 2){
        printf("Erreur de format de fichier\n");
        fclose(fp);
        return 0;
    }

    if( c != 2){
        printf("Erreur de format de fichier\n");
        fclose(fp);
        return 0;
    }
//ALLOCATE THE FILE TO THE STRUCT
    succes = allouer(PLAT, PLAT->nl, PLAT->nc, PLAT->dep.indl, PLAT->dep.indc, PLAT->arr.indl, PLAT->arr.indc, PLAT->longdem, PLAT->sumdem );
    if(succes==0) {
        printf("Erreur d'allocation\n");
        fclose(fp);
        return 0;
    }
    for(i=0; i< PLAT->nl; i++){
        for(j=0; j<PLAT->nc; j++){
            c=fscanf(fp, "%d", &PLAT->grille[i][j]);
            if(c != 1){
                printf("Erreur de format de fichier\n");
                fclose(fp);
                return 0;
            }
        }
    }
    fclose(fp);
    ELEMENT *P_sommet = nouvel_element(PLAT->dep);
    if (P_sommet==NULL){
        printf("Erreur d'allocation\n");
        return 0;
    }
    empiler (&PLAT->chemin,P_sommet);
    PLAT->longcur=1;
    PLAT->sumcur=PLAT->grille[PLAT->dep.indl][PLAT->dep.indc];
    //ABOVE LINE INITIALISES THESE THINGS WHEN THE FILE IS READ
    return 1;
}
//AFFICHE - PRINT GRILL ONLY
void affiche_grille(PLATEAU jeu){
    int i,j;
    printf("\nEtat du jeu\n");
    for(i=0; i < jeu.nl; i++){
        for(j=0; j < jeu.nc; j++){
            if (jeu.dep.indl == i  && jeu.dep.indc == j){
                printf("D %d\t", jeu.grille[i][j]);
            }
            else if (jeu.arr.indl == i && jeu.arr.indc == j){
                printf("%d A\t", jeu.grille[i][j]);
            }
            else printf("%d\t",jeu.grille[i][j]);
        }
        printf("\n");
    }
    printf("\n");//Final new line
}

5.makefile

CC = gcc
CFLAGS = -I . #-Wall
DEPS = proj.h
OBJ = proj.o allocate_plat.o pile.o grille.o

%.o: %.c $(DEPS)
    $(CC) $(CFLAGS) -g -c -o $@ $<

proj: $(OBJ)
    gcc $(CFLAGS) -g -o $@ $^

6.示例游戏文件plateau1.txt,第一行是#rows和columns,第2和第3个起点和终点坐标,第4个是所需的路径长度和所需的网格值之和,最后4行是网格。

4 4
1 1
4 4
11 96
10 13 2 5
3 15 9 4
8 6 11 14
7 12 1 16

【问题讨论】:

  • 你有很多未初始化的指针。例如,你永远不会打电话给initialiser_pile
  • main() 中,您声明ELEMENT *P_elt,但从不分配它。但这没关系,因为你也从不使用它。
  • lire 结尾处empiler 之前在allocate_plat 中调用initialiser_pile 有助于谢谢。不再是分段错误。
  • 在你的循环中,最后一个元素永远不会为空,除非随机的机会,因为你从未初始化它。 P_elt != NULL (总是)是真的。结果,循环继续超出元素范围并访问一些导致段错误的随机地址。

标签: c pointers struct segmentation-fault


【解决方案1】:

你有很多未初始化的指针。例如,你永远不会打电话给initialiser_pile。 – 巴尔马尔

allocate_plat 中的lire 末尾处empiler 之前调用initialiser_pile 有助于感谢。不再是分段错误。 ——卢斯肯蒂安

【讨论】:

    猜你喜欢
    • 2015-06-19
    • 2022-07-01
    • 2020-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多