提问人:Hogan 提问时间:11/15/2023 最后编辑:Hogan 更新时间:11/15/2023 访问量:88
每当我尝试打印字符串时,我的代码都会出现段错误
My code keeps segfaulting whenever I try to print strings
问:
我正在开发一款在 Linux 终端中运行的游戏。我一直在研究一个系统,以加载地图文件,将其转换为自定义结构的字符串,然后打印结构所包含的字母和颜色。问题是每当我使用 .问题代码如下:printf("%s", myString);
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define BUFFLEN 3
#define DICLEN 3
/*a structure that holds basic tile info*/
typedef struct{
char letter;
char *color;
char *name;
} tile;
/*a struture that holds general map info*/
typedef struct{
const int mapHight;
const int mapWidth;
const int mapSize;
const char *mapname;
} mapinfo;
/*dictionary that holds tiles*/
tile dic[DICLEN] = {
{'T', "\033[38;5;2m", "Tree"},
{' ', "\033[0m", "Path1"},
{'\n', "\033[0m", "newLine"}
};
/*return a tile when given a name*/
tile dictionary(char *tileName){
int i = 0;
for (; i<DICLEN; i++){
if ( (strcmp(tileName, dic[i].name) ) == 0){
goto END;
}
}
goto ERROR;
END:
return dic[i];
ERROR:
fprintf(stderr, "that string is unreconnized");
exit(-1);
}
/*gets map size to make into an array*/
mapinfo getMapSize(char *mapName){
char mapFilePath[24] = "maps/";
strcat(mapFilePath, mapName);
char buffer[BUFFLEN];
FILE *mapfile = fopen(mapFilePath, "r");
for(int i; i < BUFFLEN; i++){
buffer[i] = getc(mapfile);
}
int mapWidth = atoi(buffer)+1;
getc(mapfile);
for(int i = 0; i < BUFFLEN; i++){
buffer[i] = getc(mapfile);
}
int mapHight = atoi(buffer);
int mapSize = mapHight * mapWidth;
fclose(mapfile);
mapinfo finalMap = {mapHight, mapWidth, mapSize, mapFilePath};
return finalMap;
}
/*initalize map; put tiles into the map array*/
void mapInit(tile *mapArray, char *mapName){
FILE *mapFile = fopen(mapName, "r");
int i = 1, o = 0;
char c;
//this is to skip over the map size information
for(;(c = getc(mapFile))!= '\n';){}
for(;(c = getc(mapFile)) != EOF; i++){
for(o = 0; o < DICLEN; o++){
if(c == dic[o].letter){
mapArray[i] = dictionary(dic[o].name);
}
}
// un-comment this line for debug if needed
//printf("%d\t%c%c\n",i, c, mapArray[i].letter);
}
fclose(mapFile);
}
int main(){
mapinfo map1Info = getMapSize("map1.map");
tile map1[map1Info.mapSize];
mapInit(map1, map1Info.mapname);
printf("%s%c\n", map1[0].color, map1[0].letter);
return 0;
}
我试图阅读的信息()是这样的:maps/map1.map
011 010
TT TT T TTT
T T TTT TTT
T TT TTT TT
TTT TTTT TT
T T TTT TT
TT TT TT TT
TT TT TTT T
T TTT TT TT
T TT T T T
TTT TT T
它应该打印一个绿色的 T
每当我更改为代码打印时,但显然,不再有颜色,我宁愿有颜色。
我试图将瓦片结构中的指针转换为数组,但编译器还是给了我警告和段错误。printf("%s%c\n", map1[0].color, map1[0].letter);
printf("%c\n", map1[0].letter);
附加说明:是的,我知道 in 应该是一个 int,以及我有需要解决的嵌套 for 循环。对于大多数代码,只放入其中足以使其工作,但不能很好地工作(尽管提示会很好,因为我仍然不知道如何解决其中一些问题)。char c
mapInit
编辑:通过调试器(GDB)运行我的代码后,这是我可以找到的:
(gdb) run
Starting program: /home/iggoth/Desktop/Programs/AKnightsTale/Game
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Program received signal SIGSEGV, Segmentation fault.
__strlen_sse2 () at ../sysdeps/x86_64/multiarch/strlen-vec.S:126
126 ../sysdeps/x86_64/multiarch/strlen-vec.S: No such file or directory.
(gdb) list
121 in ../sysdeps/x86_64/multiarch/strlen-vec.S
(gdb)
我没有找到任何其他信息
编辑2:运行Backtrace命令后:
(gdb) run
Program received signal SIGSEGV, Segmentation fault.
__strlen_sse2 () at ../sysdeps/x86_64/multiarch/strlen-vec.S:126
126 ../sysdeps/x86_64/multiarch/strlen-vec.S: No such file or directory.
(gdb) backtrace
#0 __strlen_sse2 () at ../sysdeps/x86_64/multiarch/strlen-vec.S:126
#1 0x00007ffff7df1d31 in __vfprintf_internal (s=0x7ffff7f95780 <_IO_2_1_stdout_>, format=0x555555556129 "%s%c\n", ap=ap@entry=0x7fffffffce70,
mode_flags=mode_flags@entry=0) at ./stdio-common/vfprintf-internal.c:1517
#2 0x00007ffff7ddb79f in __printf (format=<optimized out>) at ./stdio-common/printf.c:33
#3 0x0000555555555906 in main () at Main.c:12
(gdb)
答:
我发现了一个明显的问题。
在代码中:
mapinfo getMapSize(char *mapName){
char mapFilePath[24] = "maps/";
:
mapinfo finalMap = {mapHight, mapWidth, mapSize, mapFilePath};
return finalMap;
}
mapFilePath
是一个局部变量,并且您将指向它的指针放入要返回的对象中,因此它将悬空(当您返回时,局部 var 消失,使指针无效)。finalMap
并不是说没有其他问题 - 代码看起来像是悬空指针问题的秘诀。
分段错误的原因可能是指针从未初始化过。或者,它可能指向已解除分配的对象。就像克里斯写的,有很多潜在的悬而未决的指针。color
最好将结构定义为具有自己的数组缓冲区。
static const int TILE_NAME_LENGTH = 16;
struct{
char letter;
char color[TILE_NAME_LENGTH];
char name[TILE_NAME_LENGTH];
} tile;
当实例化 时,您将调用将所有值设置为零(例如 ),除非您有像数组中那样的初始值。这样,没有初始值的 char 数组就是空字符串。tile
memset
memset(pTile, 0, sizeof(tile))
dic
复制项目时,您需要一个用于从源复制到目标的函数。如果成员是数组,则不允许进行简单赋值。const tile *
tile *
=
评论
fopen
char mapFilePath[24]
PATH_MAX