The cause of the segmentation fault is unknown.

Asked 2 years ago, Updated 2 years ago, 294 views

We are developing a program for the task of measuring CPU time.
I compiled the two programs below and ran them.
Normal compilation is fine, but if you compile and run with the optimization option -O2 indicated in the task, Segmentation fault will be displayed.Where is the mistake?If you don't mind, please let me know.

The error message appears as follows:
The compiler is Cygwin.

megum@DESKTOP-E9B0HPJ~/B8
$ gcc-O2ita_db.ciata_cpu3.c

megum@DESKTOP-E9B0HPJ~/B8
$ ./a
key = AAC
Segmentation fault

If you paste the contents of iata_data.csv, the number of characters will exceed, so it will be a copy of the linked data.

http://www.photius.com/wfb2001/airport_codes_alpha.html

#include<stdio.h>
# include <time.h>
# include "ita_db.h"

int main (void)
{
  db_tdb;
  char key [KEY_LEN+1];
  char*data;
    inti;
 
    
  db_init(&db);
  db_hash_load(&db);

  /* Enter airport code to output data; repeat to EOF*/
  for(;;){
    fprintf(stderr, "key=");
    if(scanf(KEY_FMT,key)==EOF) {break;}
    clock_tclk_start, clk_end;
    clk_start=clock();
    for (i=0; i<=100000;i++)
    {
        data=db_hash_search(&db,key);
    }
    clk_end = clock();
    fprintf(stderr, "cpu=%11.6f[sec]\n", (double)(clk_end-clk_start)/CLOCKS_PER_SEC);
    if(data==NULL) {printf("NORECORD\n");}
    else {printf("%s=>%s\n", key, data);}
  }

  return 0;
}
#include<stdio.h>
# include <stdlib.h>
# include <string.h>
# include <assert.h>
# include "ita_db.h"
/* US>Macro*/ to determine if c is a new line symbol
# define IS_EOL(c)=='\n'||(c)=='\r')

/* Functions used only internally in iata_db.c */
static void extract_data(char line[], char key[], char data[]);
static void record_set(record_t*r, char key[], char data[]);

void db_init(db_t*db)
/* db_t Variable Initialization */
{
  inti;
  db->n=0;
  for(i=0;i<MAX_RECORDS;i++){
    strcpy(db->record[i].key, "");
    db->record[i].data=NULL;
  }
}

void db_load(db_t*db)
/* Load data from file IATA_F into the db_t variable */
{
  FILE*fp;
  charline [KEY_LEN+1+DATA_LEN+1];
  char key [KEY_LEN+1];
  char data [DATA_LEN+1];

  /* Open File*/
  if(((fp=fopen(IATA_F, "r"))==NULL){
    fprintf(stderr, "File(%s) cannot be opened\n", IATA_F);
    exit(1);
  }

  /* Load Data*/  
  while(fgets(line,DATA_LEN,fp)!=NULL){
    /* Error if input data exceeds maximum number of records allowed*/
    if(MAX_RECORDS<=db->n){
      fprintf(stderr, "MAX_RECORDS(%d)<=n(%d)\n", MAX_RECORDS, db->n);
      exit(1);
    }
    /* Cut key and data from line*/
    extract_data(line, key, data); 
    /* db->nth record contains key and data, increasing db->n by 1*/
    record_set(&db->record[db->n], key, data); 
    db->n++;
  }

  fclose(fp);
}

static void record_set (record_t*r, char key[], char data[])
/* Write key and data to the record pointed to by r (data is dynamically assigned) */
{
  assert(r!=NULL);
  assert(key!=NULL);
  assert(data!=NULL);
  /* key*/
  assert(strlen(key)<=KEY_LEN); 
  strcpy(r->key,key);
  /* data*/
  assert(strlen(data)<=DATA_LEN); 
  r->data=(char*)malloc(sizeof(char)*(strlen(data)+1));
  strcpy(r->data,data);
}

static void extract_data(char line[], char key[], char data[])
/* Extract key and data from line*/
{
  assert(line!=NULL);
  assert(key!=NULL);
  assert(data!=NULL);
  intk;

  /*  Check if one line of the file is too long to fit in the line*/
  /*  Line is not a new line at the end → 1 line is too long and error */
  if(!IS_EOL(line[strlen(line)-1]){
    fprintf(stderr, "line length exceeded line size\n";
    exit(1);
  }

  /* The leading KEY_LEN character is key*/
  intp_key = 0;
  for(k=0;k<KEY_LEN;k++){
    key[k] = line [p_key+k]; 
  }
  key[k] = '\0';

  /* KEY_LEN+ From the first character up to the new line symbol data*/
  intp_data=KEY_LEN+1;
  for(k=0;k<DATA_LEN;k++){
    if(IS_EOL(line[p_data+k])) {break;}
    data[k] = line[p_data+k];
  }
  data[k] = '\0';
}

void db_dump(db_t*db)
/* Output all data of type db_t variable */
{
    inti;
    for (i=0; i<MAX_RECORDS;i++)
    {
        printf("[%d]", i);
        if(db->record[i].data!=NULL)
        {
            printf("%s%s", db->record[i].key, db->record[i].data);
        }
        printf("\n");
    }
}

char*db_linear_search(db_t*db, char key[])
{
    inti;
    for (i=0; i<MAX_RECORDS;i++)
    {
        if(strcmp(key,db->record[i].key)==0)
        {
            return db->record[i].data;
            break;
        }
    }
    return NULL;
}

char*db_binary_search(db_t*db, char key [KEY_LEN+1])
{
    int low = 0;
    int high = db->n-1;
    int mid;
    for (;;)
    {
        mid=(high+low)/2;
        if(strcmp(key,db->record[mid].key)==0)
        {
            return db ->record [mid].data;
        }
        else if (strcmp(key, db->record[mid].key)>0)
        {
            low = mid+1;
        }
        else if (strcmp(key, db->record[mid].key)<0)
        {
            high = mid-1;
        }
        if(high<low) {break;}
    }
    return NULL;
}

int db_hash_f(char key[])
{
  inti;
  intv = 0;
  for(i=0;key[i]!='\0';i++){
    v=(v<<5)+(key[i]-'A');
  }
  return v%MAX_RECORDS;
}

void db_hash_load(db_t*db)
{
  FILE*fp;
  charline [KEY_LEN+1+DATA_LEN+1];
  char key [KEY_LEN+1];
  char data [DATA_LEN+1];
    inth;
    intm = MAX_RECORDS;

  /* Open File*/
  if(((fp=fopen(IATA_F, "r"))==NULL){
    fprintf(stderr, "File(%s) cannot be opened\n", IATA_F);
    exit(1);
  }

  /* Load Data*/  
  while(fgets(line,DATA_LEN,fp)!=NULL){
    /* Error if input data exceeds maximum number of records allowed*/
    if(MAX_RECORDS<=db->n){
      fprintf(stderr, "MAX_RECORDS(%d)<=n(%d)\n", MAX_RECORDS, db->n);
      exit(1);
    }
    /* Cut key and data from line*/
    extract_data(line, key, data); 
    /* db->nth record contains key and data, increasing db->n by 1*/
    h = db_hash_f(key);
    while(strcmp(db->record[h].key, "")!=0)
    {
        h++;
        if(h==m) {h=h-m;}
    }
    record_set(&db->record[h], key, data); 

  }

  fclose(fp);
}

char*db_hash_search(db_t*db, char key [KEY_LEN+1])
{
    inth;
    inti;
    intm = MAX_RECORDS;
    for (i=0;i<=MAX_RECORDS;i++)
    {
        if(strcmp(db->record[h].key,key)==0)
        {
            return db->record[h].data;
            break;
        }
        h++;
        if(h==m) {h=h-m;}
    }
    return NULL;
}
/*
  If the following line of _USE_MINI__ is defined, iata_mini.csv will be: 
  iata_data.csv is used when the following line is commented out
*/
/*#define__USE_MINI__*/

# ifdef__USE_MINI_
/* Test version definition*/
#define IATA_F "iata_mini.csv" /* Airport Data File */
#define MAX_RECORDS 16/*Limited number of records*/
# else
/* Defining Full Set*/
#define IATA_F "iata_data.csv" /* Airport Data File */
# define MAX_RECORDS 6000 / *Limited number of records */
#endif


#define KEY_LEN3 / *Number of characters in airport code (key) */
#define KEY_FMT "%3s" / *Format for airport code (key) */
#define DATA_LEN127 /* Maximum number of characters in airport data *


/* 1 record of data*/
typeef structure {
  char key [KEY_LEN+1]; /* Airport Code (key) */
  char*data; /* pointer to airport detail data (character array) */
} record_t;


/* Database (all data)*/
typeef structure {
  intn; /* Number of data (records) */
  record_record [MAX_RECORDS]; /* Array of data (records) */
} db_t;


void db_init(db_t*db); /*initialization*/
void db_load(db_t*db); /* Read data from file */
void db_dump(db_t*db); /* dump (all data output) */

char*db_linear_search(db_t*db, char key[]); /* linear search*/
char*db_binary_search(db_t*db,char key[]); /*Binary Search*/

int db_hash_f(char key[]); /* hash function */
void db_hash_load(db_t*db); /* Read data (for hash) */
char*db_hash_search(db_t*db, char key[]); /* Search by hash*/

c windows

2022-09-30 22:00

2 Answers

db_hash_search() You seem to be measuring the execution speed of the function
The auto variable h does not appear to have been initialized. (Typically assigned from the stack area, the content should be indefinite or something to keep the contents of the stack area secret)

Are you trying to process this process from the continuation of the search you called last time? So
Maybe it needs to be static (if static, uninitialized is 0)

 char*db_hash_search(db_t*db, char key [KEY_LEN+1])
{
    static inth;//<==modifying
    inti;

Edit: (The content may change depending on the randomization of the location, but it doesn't seem to be related to the auto variable, so delete it)


2022-09-30 22:00

Perhaps the core dump occurred by accidental.
There is a potential bug, as shown below, which may have been caused by operating conditions.

Debugging allows VC++ instead of Cygwin(gcc) to uncheck the default and compile, db_hash_search(...) of ita_db.c pointed out in the comment db_hash_search(...) if (strcmp(db->record[h].key,key)==0) is an exception.

It works even if you initialize the variable h with some fixed value (maybe it's a static variable like @ori-san's answer?), but now that you mention it, there seems to be no process equivalent to the hash of the function name db_hash_search(...).

If you look at iata_db.c in that way, there is a similar form of processing to db_hash_load(...), where the variable h is set to db_hash_f(key); and then similar loops and string comparison is done.

Therefore, it seems that the correct way to name the function is to define the current inth; and initialize the uninitialized variable with db_hash_f(key) as follows:

 char*db_hash_search(db_t*db, char key [KEY_LEN+1])
{
    inth = db_hash_f(key); // <==
    inti;
hereinafter abbreviated


2022-09-30 22:00

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.