Как исправить ошибку сегментации?

В приведенной ниже программе отображается ошибка: «ошибка сегментации (сброс ядра)».

Он должен отображать запись плоского файла с использованием вектора, читать запись каждой строки, получать поля и возвращать их обратно в вектор r_record. И вдавить обратно в стол.

//.. includes
#define LIMIT 72
#define FIELD 25

using namespace std;
typedef vector <string> record_t;
typedef vector <record_t> table_t;
char line[FIELD];   
string s_field;
table_t table;
record_t r_record;

void getField(char s[LIMIT])
{
    char field[LIMIT];      
    int i=0;
    r_record.clear();
    while(s[i]  != '\n')
    {   
        if (s[i] != '\t' )
        {                                                       
            field[i] = s[i];
            //*s_field = *s_field+1;        
        }               
        i++;
    }
    s_field = field;            
    r_record.push_back(s_field);
} 

void getLine(FILE *fp)
{
    char c;
    int j=0;    
    table.clear();
    l1:while ( (c = getc(fp)) != EOF ) 
    {  
        if( c != '\n' )
        {
           line[j] = c;

        }
        j++;
    }   
    getField(line);
    table.push_back(r_record);
    if(c != EOF)
        goto l1;                        
    cout<<table.size(); 
} 

int main()
{
    double total_time;  
    clock_t start, end;
    start = clock();//time count starts 
    FILE *f1;   
    f1 = fopen("somesamplefile.txt","r+");      
    getLine(f1); 

    end = clock();//time count stops 
    total_time = ((double) (end - start)) / CLOCKS_PER_SEC; //calulate total time
    printf("\nTime taken to print  %f\n", total_time);

    return 0;
}

person Community    schedule 29.12.2014    source источник
comment
Было бы лучше показать пример ввода, вызывающего сбой. Вы запускали программу в отладчике?   -  person Retired Ninja    schedule 29.12.2014
comment
проверьте if ( f1 == NULL ) exit(EXIT_FAILURE); перед выполнением getLine(f1);   -  person M.M    schedule 29.12.2014
comment
char c; должно быть int c; иначе цикл EOF не работает   -  person M.M    schedule 29.12.2014
comment
getLine вызывает переполнение буфера, его необходимо остановить до достижения LIMIT. getField также необходимо остановить до достижения LIMIT. Вы можете избежать этих проблем, используя std::string и std::getline.   -  person M.M    schedule 29.12.2014
comment
если бы я использовал std::string, как получить поле и номер строки, которые должны быть выполнены без использования fstream   -  person    schedule 29.12.2014


Ответы (2)


Я бы обратил внимание на комментарий @MattMcNabb о проверке ограничений перед присвоением значений отдельным символам в строках.

Кроме того, вы не завершили нулем field в getField. Без этого заявление

    s_field = field;

может получить доступ к данным за пределами границ и вызвать неопределенное поведение.

void getField(char s[LIMIT])
{
    // **** CORRECTION *****
    // I am guessing you meant to use field[FIELD].
    // char field[LIMIT];      
    char field[FIELD];

    int i=0;
    r_record.clear();

    // **** CORRECTION *****
    // Add a check to stop going beyond the limits of the array.
    // while(s[i]  != '\n')
    while( i < FIELD-1 && s[i]  != '\n')
    {   
        if (s[i] != '\t' )
        {                                                       
            field[i] = s[i];
            //*s_field = *s_field+1;        
        }               
        i++;
    }

    // **** CORRECTION *****
    // Add this
    field[i] = '\0';

    s_field = field;            
    r_record.push_back(s_field);
} 

Кроме того, я думаю, вы хотели использовать

char line[LIMIT];   

вместо

char line[FIELD];   
person R Sahu    schedule 29.12.2014
comment
Я заменил ваш код, но он печатает только одну запись, но квартира содержит 100000 записей. - person ; 30.12.2014

сердечно 001 25 город1 сердечно 002 26 город1 сердечно 003 27 город1 сердечно 004 25 город1 сердечно 005 28 город1 сердечно 006 29 город1 сердечно 007 30 город1 сердечно 001 25 город1 сердечно 002 26 город1 сердечно 003 27 город1

в тексте есть формат с разделителями табуляции, который должен отображаться неправильно

программа после исправления

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <fstream>
#include <string>
#include <cctype>
#include <cstdio>
#include <ctime>
#include <vector>
#include <sstream>
#include <algorithm>
#include <iterator>
#include <sys/stat.h>
#include <iterator>
#include <exception>
#include <dirent.h>
#include <unistd.h>
#include <map>
#include <unordered_map>
#include <sys/timeb.h>
#include <stdexcept>                                                     // std::out_of_range
#include <time.h>
#define LIMIT 22
#define FIELD 8

using namespace std;
typedef vector <string> record_t;
typedef vector <record_t> table_t;
char line[LIMIT];   
string s_field;
table_t table;
record_t r_record;

vector <string>::iterator t_record;

void getField(char s[LIMIT])
{
    // **** CORRECTION *****
    // I am guessing you meant to use field[FIELD].
    // char field[LIMIT];      
    char field[FIELD];

    int i=0;
    r_record.clear();

    // **** CORRECTION *****
    // Add a check to stop going beyond the limits of the array.
    // while(s[i]  != '\n')
    while( i < FIELD-1 && s[i]  != '\n')
    {   
        if (s[i] != '\t' )
        {                                                       
            field[i] = s[i];
            //*s_field = *s_field+1;        
        }               
        i++;
    }

    // **** CORRECTION *****
    // Add this
    field[i] = '\0';

    s_field = field;            
    r_record.push_back(s_field);    
} 

void getLine(FILE *fp)
{
    char c;
    int j=0;    
    table.clear();
    l1:while ( j < LIMIT-1 ) 
    {  
        c = getc(fp);
        if( c != '\n' )
        {
           line[j] = c;
            j++;
        }                 
    }   
    line[j] = '\0';
    if( c!= EOF )    
    {       
        getField(line);
        table.push_back(r_record);
        j=0;
        goto l1;
    }

} 

int main()
{
    double total_time;  
    clock_t start, end;
    start = clock();//time count starts 
    FILE *f1;   
    f1 = fopen("somesamplefile.txt","r+");      
    getLine(f1); 
    for(t_record = r_record.begin(); t_record != r_record.end(); ++t_record )
    {
      cout <<*t_record <<endl;
    }
    cout<<table.size(); 
    end = clock();//time count stops 
    total_time = ((double) (end - start)) / CLOCKS_PER_SEC; //calulate total time
    printf("\nTime taken to print  %f\n", total_time);

    return 0;
}
person Community    schedule 30.12.2014