此代码生成段错误。我哪里出错了?

时间:2012-11-14 04:35:55

标签: c++ strtok

此代码的目标是从制表符分隔文件中的字段快速读取一些数据并对其进行排序。我发现当我运行此代码时,我遇到了分段错误。我认为这与我对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命令中。如果没有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的值。

1 个答案:

答案 0 :(得分:1)

使用g++ -Wall -g进行编译,我发现您需要包含string.h才能获得strtok,而operator<需要返回一些内容,如果没有更早的if fopen语句是真的。之后......

  1. 您没有检查table.txt的返回值,因此我找到的第一个段错误是当我没有创建strtok进行测试时。

  2. 您也没有检查NULL的返回值,因此如果不存在匹配的列,那么您可以将atoi传递给gdb,并在那里获得段错误

  3. 当程序崩溃时,您需要使用bt的{​​{1}}命令来找出导致崩溃的行。