ошибка сегментации на getline в Ubuntu - PullRequest
1 голос
/ 17 июля 2011

У меня знаменитая ошибка сегментации.Я проследил это до одной строки в коде (getline).Вот кто-то с похожей проблемой, также в Ubuntu:

http://www.daniweb.com/software-development/cpp/threads/329191

Обратите внимание, что getline возвращает -1 после ошибки сегментации, но это не могло быть концом потока(в моем случае).

Когда поток меньше, все идет хорошо.Как мы можем вывести из вывода, ошибка сегментации находится в строке 98.

     1  /* 
     2   * File:   RequestDispatcher.cpp
     3   * Author: albert
     4   * 
     5   * Created on July 8, 2011, 7:15 PM
     6   */
     7  
     8  #include "iostream"
     9  #include "fstream"
    10  #include "stdlib.h"
    11  #include "stdio.h"
    12  #include "cstring"
    13  #include "algorithm"
    14  
    15  #include "RequestDispatcher.h"
    16  #include "Functions.h"
    17  
    18  #define PROXIES 1
    19  
    20  RequestDispatcher::RequestDispatcher()
    21  {
    22  }
    23  
    24  RequestDispatcher::RequestDispatcher(const RequestDispatcher& orig)
    25  {
    26  }
    27  
    28  RequestDispatcher::~RequestDispatcher()
    29  {
    30  }
    31  
    32  int RequestDispatcher::addRequest(string host, string request, IResponseReceiver* response_receiver)
    33  {
    34      RequestInfo info;
    35      info.request_index = request_info.size();
    36      info.host = host;
    37      info.request = request;
    38      info.response_receiver = response_receiver;
    39      request_info.push_back(info);
    40      return info.request_index;
    41  }
    42  
    43  void RequestDispatcher::run()
    44  {
    45      if (request_info.size()==0)
    46      {
    47          return;
    48      }
    49      FILE* pipe[PROXIES];
    50      int per_proxy = (request_info.size() + PROXIES - 1) / PROXIES;
    51      int count_pipes = (request_info.size() + per_proxy - 1) / per_proxy;
    52      for (int pipe_index=0; pipe_index<count_pipes; ++pipe_index)
    53      {
    54          int from = pipe_index * per_proxy;
    55          int to = min(from + per_proxy, int(request_info.size()));
    56          cout << "FROM: "<< from << "; TO: " << to;
    57          const char* cmd = generateCmd(from, to);
    58          pipe[pipe_index] = popen(cmd, "r");
    59          if (!pipe[pipe_index])
    60          {
    61              cerr << "Error executing command in RequestDispatcher::run()";
    62          }
    63      }
    64      string result[PROXIES];
    65      bool finished[PROXIES];
    66      for (int pipe_index=0; pipe_index<count_pipes; pipe_index++)
    67      {
    68          finished[pipe_index] = false;
    69      }
    70      int count_finished = 0;
    71      char* buffer;
    72      size_t buffer_length=1024;
    73      buffer = (char *) malloc (buffer_length + 1);
    74      while (count_finished < count_pipes)
    75      {
    76          cout << "D\n";
    77          fflush(stdout);
    78          for(int pipe_index=0; pipe_index<count_pipes; ++pipe_index)
    79          {
    80              cout << "E\n";
    81              fflush(stdout);
    82              if (finished[pipe_index])
    83              {
    84                  continue;
    85              }
    86              cout << "Getline" << buffer_length << "\n";
    87              ssize_t bytes_read = getline(&buffer, &buffer_length, pipe[pipe_index]);
    88              cout << "Getline Done ("<<bytes_read<< "," << buffer_length << ")\n";
    89              fflush(stdout);
    90              while (bytes_read>0)
    91              {
    92                  for (int i=0; i<bytes_read; i++)
    93                  {
    94                     result[pipe_index] += buffer[i];
    95                  }
    96                  cout << "P\n";
    97                  fflush(stdout);
    98                  bytes_read = getline(&buffer, &buffer_length, pipe[pipe_index]);
    99                  cout << "Bytes read ("<<bytes_read<<","<< buffer_length << ")\n";
   100                  fflush(stdout);
   101  
   102              }
   103              if (bytes_read == -1)  // then finished this pipe
   104              {
   105                  string* r = &result[pipe_index];
   106                  //cout << *r;
   107                  finished[pipe_index] = true;
   108                  ++count_finished;
   109                  cout << "HI\n";
   110                  fflush(stdout);
   111                  // delete trailing '\0' from result
   112                  pclose(pipe[pipe_index]);
   113                  result[pipe_index] = result[pipe_index].substr(0, result[pipe_index].length()-1);
   114                  int pos = r->find("RESPONSE_DATA");
   115                  int valuepos, endvaluepos;
   116                  int request_index, length;
   117                  string headers;
   118                  int headerslength;
   119                  string body;
   120                  int bodypos, bodylength;
   121                  while (pos!=r->npos)
   122                  {
   123                      valuepos = r->find("REQUEST_INDEX=", pos) + 14;
   124                      endvaluepos = r->find("\n", valuepos);
   125                      request_index = pipe_index * per_proxy + atoi(r->substr(valuepos, endvaluepos-valuepos).c_str());
   126  
   127                      cout << "REQUEST_INDEX " << request_index;
   128  
   129                      valuepos = r->find("LENGTH=", pos) + 7;
   130                      endvaluepos = r->find("\n", valuepos);
   131                      length = atoi(r->substr(valuepos, endvaluepos-valuepos).c_str());
   132  
   133                      pos = r->find("START", pos)+5;
   134                      bodypos = r->find("\r\n\r\n", pos)+4;
   135                      headerslength = bodypos-pos-4;
   136                      bodylength = length-headerslength-4;
   137                      headers = r->substr(pos, headerslength);
   138                      body = r->substr(bodypos, bodylength);
   139                      request_info[request_index].response_receiver->notifyResponse(headers, body, request_index);
   140  
   141                      pos=r->find("RESPONSE_DATA", pos+length);
   142                  }
   143              }
   144          }
   145      }
   146      cout << "\n?\n";
   147      fflush(stdout);
   148      free(buffer);
   149      request_info.clear();
   150  }
   151  
   152  const char* RequestDispatcher::generateCmd(int first_request, int to_request)
   153  {
   154      string r("/home/albert/apachebench-standalone-read-only/ab -a");
   155      for (int i=first_request; i<to_request; i++)
   156      {
   157          r.append(" '");
   158          r.append(request_info.at(i).request);
   159          r.append("'");
   160      }
   161      ofstream out("/home/albert/apachebench-standalone-read-only/debug");
   162      if(! out)
   163      {
   164          cerr<<"Cannot open output file\n";
   165          return "";
   166      }
   167      out << r.c_str();
   168      out.close();
   169      return "/home/albert/apachebench-standalone-read-only/debug";
   170      /*int size = strlen("/home/albert/apachebench-standalone-read-only/ab -a");
   171      for (int i=first_request; i<to_request; i++)
   172      {
   173          size += 2+strlen(request_info.at(i).request)+1;
   174          cout << "len: " << strlen(request_info.at(i).request) << "\n";
   175          cout << "total: " << size << "\n";
   176      }
   177      size += 1;
   178      char* cmd = new char[size];
   179      strcpy(cmd, "/home/albert/apachebench-standalone-read-only/ab -a");
   180      for (int i=first_request; i<to_request; i++)
   181      {
   182          cout << "LEN: " << strlen(cmd) << "\n";
   183          cout << "NEXT: " << strlen(request_info.at(i).request) << "\n";
   184          fflush(stdout);
   185          strcat(cmd, " '");
   186          strcat(cmd, request_info.at(i).request);
   187          strcat(cmd, "'");
   188      }
   189      cout << "LEN: " << strlen(cmd) << "\n";
   190      fflush(stdout);
   191      return cmd;*/
   192  }

Когда я запускаю / home / albert / apachebench-standalone-only-read-/ debug из командной строки, все работает отлично,Возвращает двоичные данные.

Конец вывода:

P
Bytes read (272,6828)
P
Bytes read (42,6828)
P
Bytes read (464,6828)
P
Bytes read (195,6828)
P
Bytes read (355,6828)
P
Bytes read (69,6828)
P
Bytes read (111,6828)
P
Segmentation fault
Bytes read (368,6828)
P
Bytes read (-1,6828)
HI
REQUEST_INDEX 46REQUEST_INDEX 48REQUEST_INDEX 44REQUEST_INDEX 0REQUEST_INDEX 45
?

Запомните "?"для выхода из цикла.После этого программа заканчивается.

Кстати, я всегда думал, что программа завершит работу из-за ошибки сегментации (правка: я ничего не сделал, чтобы ее перехватить).

В ответна некоторые ответы: Кажется, существуют разные версии getline, и я, кажется, использую документированную здесь:

http://www.kernel.org/doc/man-pages/online/pages/man3/getline.3.html

1 Ответ

0 голосов
/ 17 июля 2011

Итак, после некоторых размышлений, я полагаю, что проблема в том, что ваш буфер записывается во время чтения. В некоторых случаях запись в буфер не завершена, и вы удаляете некоторые данные из него (что может означать, что вы можете прочитать пустой буфер, потому что запись не завершена). Это потому, что вы используете popen и просто передаете данные из другого процесса. Я рекомендую вам использовать стандарт C ++ для getline (хотя оба они небезопасны) и что у вас есть некоторая свобода для чтения данных из канала. Возможно, вам нужна логика повторов, поскольку я не могу придумать, как решить эту проблему. Если кто-то знает, пожалуйста, напишите об этом, я публикую это, потому что это то, что я считаю вероятным виновником проблемы.

Также, если вы пишете код на C ++, я настоятельно рекомендую вам использовать библиотеки C ++, чтобы вы не постоянно смешивали и не приводили между типами (такими как string to char * и т. Д., Это просто избавит вас от хлопот) и что вы используете более безопасные версии методов, чтобы избежать ошибок, таких как переполнение буфера.

...