我在构建一个用图表做各种事情的程序时遇到了这个问题。
我使用代码块在 C 中编写了代码,如果我正常运行它(通过“构建和运行”)程序“工作”(它仍然没有完成),但是如果我尝试通过调试器运行代码它会停止段错误
。这很奇怪。
为了解决这个问题,这里摘录了一些我的代码,抱歉弄得一团糟:
主.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
图.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;
图.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;
}
图形解析器.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));
调试器在这里调用“段错误”,但我不明白为什么。 您是否知道为什么代码在没有调试器的情况下运行而不是在有调试器的情况下运行,并给出该错误? 预先感谢您提供的所有帮助。
最佳答案
Graph G = malloc(sizeof(struct TGraph));
((AdjList *)(G->adj))->nodes = malloc(nodes_count * sizeof(List));
您正在使用 malloc
为 G
分配内存,但您从未使用有效值对其进行初始化,因此取消引用 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));
关于代码运行正常但调试给出 "Segmentation fault",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34400972/