C 评论2自由时的分段错误(Sokoban游戏)
从昨天开始,我一直在尝试解决分割错误,这让我发疯。。。 所以我有一个程序,我用它来实现sokoban游戏,其中给出了一张地图,并给出了一个类似“NSEW”的计划,这意味着我希望玩家先向北移动,然后向南移动,等等。。。在给定的地图上C 评论2自由时的分段错误(Sokoban游戏),c,segmentation-fault,fault,C,Segmentation Fault,Fault,从昨天开始,我一直在尝试解决分割错误,这让我发疯。。。 所以我有一个程序,我用它来实现sokoban游戏,其中给出了一张地图,并给出了一个类似“NSEW”的计划,这意味着我希望玩家先向北移动,然后向南移动,等等。。。在给定的地图上 map* replay(map* map_loaded, int length, char* plan){ map* new_map=move(map_loaded,plan[0]); map* old_map=deep_copy(new_map);
map* replay(map* map_loaded, int length, char* plan){
map* new_map=move(map_loaded,plan[0]);
map* old_map=deep_copy(new_map);
for (int i=1 ; i<length ; i++){
free(new_map->p_char);
free(new_map);
new_map=move(old_map,plan[i]);
free(old_map->p_char);
free(old_map);
old_map=deep_copy(new_map);
}
free(old_map->p_char);
free(old_map);
return new_map;
}
移动功能执行一次移动
深度副本生成映射结构的深度副本:
map* deep_copy(map* map_loaded){
map* new_map=malloc(sizeof(map));
char* p_array=map_loaded->p_char;
int width=map_loaded->width;
int height=map_loaded->height;
new_map->width=width;
new_map->height=height;
char* p_new=malloc(sizeof(char)*width*height);
for (int i=0 ; i<width*height ; i++){
p_new[i]=p_array[i];
}
new_map->p_char=p_new;
return(new_map);
}
我有一个分割错误。。。但如果我这样做:
//free(old_map->p_char);
//free(old_map);
一切都很完美!!
我真的不明白为什么。。。问题是如果我做了那些免费的valgrind告诉我我没有allocs那么多免费的,这是正常的
我真的很感激你给我的任何帮助。。。
如果你有足够的勇气读到我的话,请提前感谢
编辑:
这是我的移动函数
map* move(map* map_loaded, char dir){
int pos=Position(map_loaded);
int width=map_loaded->width;
map* new_map=deep_copy(map_loaded);
char* p_new_array=new_map->p_char;
switch(dir){
case 'N':
if (p_new_array[pos-width]=='#'){ // Si il y a un mur au dessus
return(map_loaded);
}
if ((p_new_array[pos-width]=='$' && p_new_array[pos-2*width]=='$')
||(p_new_array[pos-width]=='$' && p_new_array[pos-2*width]=='*')
||(p_new_array[pos-width]=='*' && p_new_array[pos-2*width]=='$')
||(p_new_array[pos-width]=='*' && p_new_array[pos-2*width]=='*')){ //s'il y a 2 caisses au dessus
return(map_loaded);
}
if ((p_new_array[pos-width]=='$' && p_new_array[pos-2*width]=='#') //s'il y a une caisse au niveau -1 et un mur au niveau -2
||(p_new_array[pos-width]=='*' && p_new_array[pos-2*width]=='#')){
return(map_loaded);
}
// On vérifie d'abord s'il y a une caisse à déplacer
if (p_new_array[pos-width]=='$' || p_new_array[pos-width]=='*'){
if (p_new_array[pos-2*width]=='.'){
p_new_array[pos-2*width]='*';
}
else {
p_new_array[pos-2*width]='$';
}
if (p_new_array[pos-width]=='*'){
p_new_array[pos-width]='.';
}
else{
p_new_array[pos-width]=' ';
}
}
//On change le char en position du joueur
if (p_new_array[pos]=='+'){
p_new_array[pos-width]='@';
p_new_array[pos]='.';
}
else if (p_new_array[pos-width]=='.'){
p_new_array[pos-width]='+';
p_new_array[pos]=' ';
}
else {
p_new_array[pos-width]='@';
p_new_array[pos]=' ';
}
break;
case 'S':
if (p_new_array[pos+width]=='#'){ // Si il y a un mur en dessous
return(map_loaded);
}
if ((p_new_array[pos+width]=='$' && p_new_array[pos+2*width]=='$')
||(p_new_array[pos+width]=='$' && p_new_array[pos+2*width]=='*')
||(p_new_array[pos+width]=='*' && p_new_array[pos+2*width]=='$')
||(p_new_array[pos+width]=='*' && p_new_array[pos+2*width]=='*')){//s'il y a 2 caisses au dessus
return(map_loaded);
}
if ((p_new_array[pos+width]=='$' && p_new_array[pos+2*width]=='#') //s'il y a une caisse au niveau +1 et un mur au niveau +2
||(p_new_array[pos+width]=='*' && p_new_array[pos+2*width]=='#')){
return(map_loaded);
}
// On vérifie d'abord s'il y a une caisse à déplacer
if (p_new_array[pos+width]=='$' || p_new_array[pos+width]=='*'){
if (p_new_array[pos+2*width]=='.'){
p_new_array[pos+2*width]='*';
}
else {
p_new_array[pos+2*width]='$';
}
if (p_new_array[pos+width]=='*'){
p_new_array[pos+width]='.';
}
else{
p_new_array[pos+width]=' ';
}
}
//On change le char en position du joueur
if (p_new_array[pos]=='+'){
p_new_array[pos+width]='@';
p_new_array[pos]='.';
}
else if (p_new_array[pos+width]=='.'){
p_new_array[pos+width]='+';
p_new_array[pos]=' ';
}
else {
p_new_array[pos+width]='@';
p_new_array[pos]=' ';
}
break;
case 'W':
if (p_new_array[pos-1]=='#'){ // Si il y a un mur en dessous
return(map_loaded);
}
if ((p_new_array[pos-1]=='$' && p_new_array[pos-2]=='$')
||(p_new_array[pos-1]=='$' && p_new_array[pos-2]=='*')
||(p_new_array[pos-1]=='*' && p_new_array[pos-2]=='$')
||(p_new_array[pos-1]=='*' && p_new_array[pos-2]=='*')){ //s'il y a 2 caisses à gauche
return(map_loaded);
}
if ((p_new_array[pos-1]=='$' && p_new_array[pos-2]=='#') //s'il y a une caisse au niveau -1 et un mur au niveau -2
||(p_new_array[pos-1]=='*' && p_new_array[pos-2]=='#')){
return(map_loaded);
}
// On vérifie d'abord s'il y a une caisse à déplacer
if (p_new_array[pos-1]=='$' || p_new_array[pos-1]=='*'){
if (p_new_array[pos-2]=='.'){
p_new_array[pos-2]='*';
}
else {
p_new_array[pos-2]='$';
}
if (p_new_array[pos-1]=='*'){
p_new_array[pos-1]='.';
}
else{
p_new_array[pos-1]=' ';
}
}
//On change le char en position du joueur
if (p_new_array[pos]=='+'){
p_new_array[pos-1]='@';
p_new_array[pos]='.';
}
else if (p_new_array[pos-1]=='.'){
p_new_array[pos-1]='+';
p_new_array[pos]=' ';
}
else {
p_new_array[pos-1]='@';
p_new_array[pos]=' ';
}
break;
case 'E':
if (p_new_array[pos+1]=='#') {// Si il y a un mur à droite
return(map_loaded);
}
if ((p_new_array[pos+1]=='$' && p_new_array[pos+2]=='$')
||(p_new_array[pos+1]=='$' && p_new_array[pos+2]=='*')
||(p_new_array[pos+1]=='*' && p_new_array[pos+2]=='$')
||(p_new_array[pos+1]=='*' && p_new_array[pos+2]=='*')){ //s'il y a 2 caisses à droite
return(map_loaded);
}
if ((p_new_array[pos+1]=='$' && p_new_array[pos+2]=='#') //s'il y a une caisse au niveau +1 et un mur au niveau +2
||(p_new_array[pos+1]=='*' && p_new_array[pos+2]=='#')){
return(map_loaded);
}
// On vérifie d'abord s'il y a une caisse à déplacer
if (p_new_array[pos+1]=='$' || p_new_array[pos+1]=='*'){
if (p_new_array[pos+2]=='.'){
p_new_array[pos+2]='*';
}
else {
p_new_array[pos+2]='$';
}
if (p_new_array[pos+1]=='*'){
p_new_array[pos+1]='.';
}
else{
p_new_array[pos+1]=' ';
}
}
//On change le char en position du joueur
if (p_new_array[pos]=='+'){
p_new_array[pos+1]='@';
p_new_array[pos]='.';
}
else if (p_new_array[pos+1]=='.'){
p_new_array[pos+1]='+';
p_new_array[pos]=' ';
}
else {
p_new_array[pos+1]='@';
p_new_array[pos]=' ';
}
break;
}
return(new_map);
}
这是载荷函数
char* Array_Creator(char* filename){
FILE* p_file = fopen(filename, "r");
char* p_array = NULL;
if (p_file == NULL) {
exit(EXIT_FAILURE);
}
else{
size_t size=1;
int c;
while (getc(p_file)!=EOF) {
size++;
}
fseek(p_file,0,SEEK_SET);
while ((c=getc(p_file))!='\n' && c!=EOF) { //on se débarasse de la première ligne
size--;
}
p_array=(char*)malloc(sizeof(char)*size);
if (p_array!=NULL) { //si jamais le malloc ne fonctionne pas
for(size_t i=0; i<size-1; i++) {
p_array[i]=(char)getc(p_file);
if (p_array[i] == '\n') { // si le caractère est une nouvelle ligne, on s'en sépare
i--; // on ajuste alors la taille et l'indice
size--;
}
}
p_array[size-1]='\0';
}
fclose(p_file);
}
return p_array;
}
//La fonction Dimensions permet de récupérer les dimensions d'une map
couple Dimensions(char *p_char){
FILE *p_file = NULL;
p_file=fopen(p_char, "r");
if (p_file == NULL) {
fprintf(stderr, "Cannot read file %s!\n", p_char);
exit(EXIT_FAILURE);
}
couple dim={0,0}; //la structure couple est déf dans le loader.h
int width = 0;
int height = 0;
int fscanf_result = 0;
fscanf_result = fscanf(p_file, "%d %d\n", &width, &height);
if (fscanf_result != 2) {
fprintf(stderr, "First line is not syntactically correct!\n");
exit(EXIT_FAILURE);
}
dim.x=width;
dim.y=height;
fclose(p_file);
return dim;
}
//La fonction Load est celle demandée et permettant de charger une carte ; elle utilise Dimensions et Array_Creator
map* load(char *filename){
map* map_loaded=malloc(sizeof(map)); //on alloue dynamiquement la map
//Dans un premier temps on récupère les dimensions
couple map_dim={0,0};
map_dim=Dimensions(filename);
map_loaded->width=map_dim.x;
map_loaded->height=map_dim.y;
//Dans un second temps on définit le tableau 1D contenant l'ensemble des éléments de la map
char* p_char=Array_Creator(filename);
map_loaded->p_char=p_char;
return map_loaded;
}
char*数组\u创建者(char*文件名){
FILE*p_FILE=fopen(文件名,“r”);
char*p_数组=NULL;
if(p_文件==NULL){
退出(退出失败);
}
否则{
尺寸=1;
INTC;
while(getc(p_文件)!=EOF){
大小++;
}
fseek(p_文件,0,SEEK_集);
而((c=getc(pèu文件))!='\n'和&c!=EOF){//
大小--;
}
p_数组=(char*)malloc(sizeof(char)*size);
如果(p_数组!=NULL){//si jamais le malloc ne fonctionne pas
对于(大小i=0;ip字符=p字符;
返回已加载的地图;
}
例如,命令行是:
./replay./data/soko.in 4 7“NSWSESNWW”在
移动
功能中,应更改所有
return(map_loaded); => return(new_map);
当move函数返回map_load时,它将两次释放map_load
代码分析
map *replay(map *map_loaded, int length, char *plan)
{
map *new_map = move(map_loaded, plan[0]); // [2] set new_map to map_loaded
map *old_map = deep_copy(new_map);
for (int i = 1 ; i < length ; i++) {
free(new_map->p_char);
free(new_map); // [3] new_map be freed,
// equivalent map_loaded be freed
new_map = move(old_map, plan[i]);
...
}
...
return new_map;
}
int main(int argc, char *argv[])
...
map *map_loaded = load(argv[1]); // [1] map_loaded be malloc
...
map *new_map = replay(map_loaded, length, plan);
...
free(map_loaded->p_char);
free(map_loaded); // [4] map_loaded be freed
...
}
map*回放(map*map\u加载,int长度,char*plan)
{
map*new_map=move(map_loaded,plan[0]);//[2]将new_map设置为map_loaded
地图*旧地图=深度复制(新地图);
for(int i=1;ip_字符);
免费(新地图);//[3]新地图被释放,
//无法释放加载的等效映射
新地图=移动(旧地图,平面图[i]);
...
}
...
返回新的地图;
}
int main(int argc,char*argv[])
...
map*map_loaded=load(argv[1]);/[1]map_loaded为malloc
...
地图*新地图=重播(地图已加载、长度、计划);
...
免费(已加载贴图->p\u字符);
释放(已加载贴图);//[4]已加载贴图将被释放
...
}
听起来好像你在破坏堆。valgrind应该在你执行无效写入时告诉你。如果没有,请在释放指针后立即尝试将所有指针设置为NULL-这样,如果你试图访问释放的内存,你会立即出错。你没有发布移动
函数否我没有发布移动函数离子因为它非常长,有很多情况,大约有200行长…但是你应该知道的是,它需要一个映射,然后返回一个新的。@Candidethoveso移动
非常重要,因为它必须执行一些malloc
调用。将其剥离,以便它只处理一个暴露错误的情况。完成!和Paul R to回答你,我已经做了你所说的,但没有改变任何事情……当然这是问题所在……非常感谢你,它工作得非常完美!!@Candidethoveso:如果答案解决了你的问题,你应该将它标记为“接受”(点击复选标记),并且投票也会很礼貌。
return(map_loaded); => return(new_map);
map *replay(map *map_loaded, int length, char *plan)
{
map *new_map = move(map_loaded, plan[0]); // [2] set new_map to map_loaded
map *old_map = deep_copy(new_map);
for (int i = 1 ; i < length ; i++) {
free(new_map->p_char);
free(new_map); // [3] new_map be freed,
// equivalent map_loaded be freed
new_map = move(old_map, plan[i]);
...
}
...
return new_map;
}
int main(int argc, char *argv[])
...
map *map_loaded = load(argv[1]); // [1] map_loaded be malloc
...
map *new_map = replay(map_loaded, length, plan);
...
free(map_loaded->p_char);
free(map_loaded); // [4] map_loaded be freed
...
}