Этот код генерирует segfault. Где я ошибся?

Цель этого кода — быстро считывать некоторые данные в память из полей в файле с разделителями табуляции и сортировать их. Я обнаружил, что когда я запускаю этот код, я получаю ошибку сегментации. Я предполагаю, что это связано с моим ограниченным знанием strtok. Я знаю, что было бы проще использовать некоторые функции c ++ для токенизации строк, однако я хотел бы, чтобы этот код выполнялся как можно быстрее. Кажется, что большинство кода на C ++ заставило бы меня излишне выделять место для новых объектов. В идеале код будет выполняться на файлах, содержащих сотни миллионов строк. Итак, это должно быть быстро.

    #include <stdlib.h>
#include <stdio.h>

#include <string>
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

class Node
{
public:
string name;
int position1;
int position2;
string desc;
float value;

bool operator<(const Node& T) const;
};

bool Node::operator<(const Node &T) const
{
int result;
result = name.compare(T.name);
if (result !=0) return(result);

if (position1 != T.position1) return(position1 < T.position1);

if (position2 != T.position2) return(position2 < T.position2);

return(false);

}

class NodeList
{
public:
vector<Node> nodes;
};int main(void)
{
string filename = "table.txt";
FILE* infile = fopen(filename.c_str(), "r");

int buflen = 1000;
char buffer[buflen];

NodeList K;
Node T;while(fgets(buffer,buflen,infile) != NULL)
{
cout<< buffer << endl;

T.name      = string(strtok(buffer, "\t\n"));
T.position1 = atoi  (strtok(NULL  , "\t\n"));
T.position2 = atoi  (strtok(NULL  , "\t\n"));
T.desc      = string(strtok(NULL  , "\t\n"));
T.value = atof  (strtok(NULL  , "\t\n"));

K.nodes.push_back(T);
}

sort(K.nodes.begin(),K.nodes.end());

return(0);

}

РЕДАКТИРОВАТЬ: Segfault происходит в команде сортировки. Без команды sort код работает нормально. Отредактировано для учета комментариев. Вот вывод отладчика:

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0xffffffffffffffe8 0x00007fff83a078bb in std::string::compare ()
(gdb) bt
#0  0x00007fff83a078bb in std::string::compare ()
#1  0x0000000100001333 in Node::operator< (this=0x7fff5fbfeef0, T=@0x1001fffe0) at test.cpp:27
#2  0x000000010000274e in std::__unguarded_linear_insert<__gnu_cxx::__normal_iterator<Node*, std::vector<Node, std::allocator<Node> > >, Node> (__last={_M_current = 0x100200000}, __val=@0x7fff5fbfeef0) at stl_algo.h:2309
#3  0x0000000100003f28 in std::__unguarded_insertion_sort<__gnu_cxx::__normal_iterator<Node*, std::vector<Node, std::allocator<Node> > > > (__first={_M_current = 0x100200200}, __last={_M_current = 0x1002581e0}) at stl_algo.h:2406
#4  0x000000010000437b in std::__final_insertion_sort<__gnu_cxx::__normal_iterator<Node*, std::vector<Node, std::allocator<Node> > > > (__first={_M_current = 0x100200000}, __last={_M_current = 0x1002581e0}) at stl_algo.h:2439
#5  0x0000000100004422 in std::sort<__gnu_cxx::__normal_iterator<Node*, std::vector<Node, std::allocator<Node> > > > (__first={_M_current = 0x100200000}, __last={_M_current = 0x1002581e0}) at stl_algo.h:2831
#6  0x00000001000019e8 in main () at test.cpp:76

Если я поднимусь на один уровень вверх и посмотрю на значения, я получу это:

(gdb) print T
$1 = (const Node &) @0x1001fffe0: {
name = {
_M_dataplus = {
<std::allocator<char>> = {
<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>},
members of std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Alloc_hider:
_M_p = 0x0
}
},
position1 = 0,
position2 = 0,
desc = {
_M_dataplus = {
<std::allocator<char>> = {
<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>},
members of std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Alloc_hider:
_M_p = 0x0
}
},
value = 0
}

Значения this.name и т. Д. Выглядят так, как будто они взяты из файла, но независимо от того, с чем он сравнивается, все значения равны 0 или NULL.

0

Решение

Компилирование с g++ -Wall -gЯ вижу что нужно включить string.h получить strtok, и ваш operator< нужно что-то вернуть, если ни один из предыдущих if заявления были правдой. После этого…

  1. Вы не проверяете возвращаемое значение fopenИтак, первый segfault, который я обнаружил, был, когда я не создал table.txt проверить с.

  2. Вы не проверяете возвращаемое значение strtok либо, так что если соответствующий столбец не существует, то вы можете передать NULL в atoi, и получите Segfault там.

Вам нужно использовать gdb«s bt Команда, когда ваша программа падает, чтобы выяснить, какая строка вызвала сбой.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]