【发布时间】: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