Как да коригирате грешката в сегментирането?

Програмата по-долу показва грешката: "грешка при сегментиране (изхвърлено ядро)".

Той трябва да покаже записа на плосък файл с помощта на вектор, да прочете записа на всеки ред и да получи полето и да го върне обратно във вектора 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 за проверка на лимитите, преди да присвоите стойности на отделните символи в низовете.

Освен това не сте прекратили null 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
Замених вашия код, но той отпечатва само един запис, но плоският съдържа 100 000 записа - person ; 30.12.2014

heartly 001 25 city1 heartly 002 26 city1 heartly 003 27 city1 heartly 004 25 city1 heartly 005 28 city1 heartly 006 29 city1 heartly 007 30 city1 heartly 001 25 city1 heartly 002 26 city1 heartly 003 27 city1

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

програма след корекцията

#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