我的析构函数需要在这个函数中做什么?

时间:2013-08-02 15:48:33

标签: c++ segmentation-fault lexer

我的程序执行正常,但最后,当我调试它时,它在调用我的析构函数后出现了分段错误。我不确定问题的原因是什么。我发布了2个相关文件。

Breakpoint 1, main () at Prog3.cc:12

12        cout << "Program executed" << endl;

(gdb) s

Program executed

~Lex (this=0x80375c4) at lex.cc:36

36      delete [] str;

(gdb) s

37      }

(gdb) s

Program received signal SIGSEGV, Segmentation fault.
0xfef49418 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string () from /usr/sfw/lib/libstdc++.so.6
(gdb) Quit

lex.h如下:

#ifndef LEX_H
#define LEX_H
#include "token.h"
#include <iostream>
#include <stdlib.h>
class Lex {
 public:
  Lex(istream& in, string fileName);
  //Lex();
  //Lex(const Lex& l);
  ~Lex();

  static const int INTLIT = 1;  
  static const int FLOATLIT = 2;
  static const int STRLIT = 3;
  static const int IDENT = 4;
  static const int PLUS = 5;
  static const int MINUS = 6;
  static const int TIMES = 7;
  static const int DIVIDE = 8;
  static const int REM = 9;
  static const int ASSIGN = 10;
  static const int LPAREN = 11;
  static const int RPAREN = 12;
  static const int COMMA = 13;
  static const int EQ = 14;
  static const int LT = 15;
  static const int LE = 16;
  static const int GT = 17;
  static const int GE = 18;
  static const int NE = 19;
  static const int SET = 20;
  static const int PRINT = 21;
  static const int WHILE = 22;
  static const int DO = 23;
  static const int END = 24;
  static const int AND = 25;
  static const int OR = 26;
  static const int IF = 27;
  static const int THEN = 28;
  static const int ELSE = 29;
  static const int ENDIF = 30;
  static const int PROGRAM = 31;
  static const int ENDOFFILE = 32;
  static const int ERROR = 33;    
  int charIndex;
  int lineIndex;
  int spaceIndex;
  int lineNum;
  int lineLength[100];
  char ch;
  bool hashCheck;  
  bool stopLoop;
  Token nextToken();  
  char nextChar();    
  char str[256][256];
  bool checkSet;
  void printLex();
  string idents[256];
  int identCount;  
  friend ostream& operator<<(ostream& out, const Token& t);
};
#endif
#include "lex.h"
#include "token.h"
#include <iostream>
#include <fstream>
#include <stdlib.h>

lex.cc就在这里。

Lex::Lex(istream& in, string fileName) {   
  stopLoop = false;
  charIndex = 0;
  lineIndex = 0;
  identCount = 0;
  lineNum = 0;  
  hashCheck = false;
  checkSet = false;  
  int tempSize;
  ifstream file;   
  string temp;  
  for (int i = 0; i < 100; ++i)
    lineLength[i] = 0;
  if (!file.is_open()) { file.open(fileName.c_str()); }    
  while(!file.eof()) {  

    std::getline(file,temp);        
    tempSize = temp.size();

    for (int i = 0; i < tempSize; ++i) {      
      str[lineNum][i] = temp[i];
      lineLength[lineNum] += 1;
    }   
    lineNum++;
  }
  file.close();   
}
Lex::~Lex() { 
delete [] str;
}
void Lex::printLex() {    
  charIndex = 0;
  lineIndex = 0;  
  while (stopLoop == false) {  
    cout << nextToken();
    // cout << "Line index: " << lineIndex << endl;
  }  
}

ostream& operator <<(ostream& out, const Token& t) {
  out << t.type() << " \t " << t.lexeme() << " \t \t " << (t.line() + 1) << " \t \t " << t.pos() << endl;
  return out;
}
bool isReal(char ch) {
  string alphabet = "abcdefghijklmnopqrstuvwxyz1234567890(){}<>+-/=!*,%&|.";
  if (alphabet.find(ch) != alphabet.npos) return true;
  else return false;
}
bool isNum(char ch) { 
  string specialChars = "1234567890.";
  if (specialChars.find(ch) != specialChars.npos) return true;
  else return false;
}
bool isNumFinal(string b) {
  int length = b.length();
  const char* temp = b.c_str();
  bool henry = true;
  for (int i = 0; i < length; ++i) {
    if (henry == false) { break; }
    henry = isNum(temp[i]);  
  }
  return henry;
}

bool isSpecialChar(char ch) {
  string specialChars = "(){}<>+-/=!*,%&|";
  if (specialChars.find(ch) != specialChars.npos) return true;
  else return false;
}

char Lex::nextChar() {   
    if (lineIndex >= lineNum) { 
      // cout << "End of file reached\n";
      stopLoop = true;
      return '#';
    }       
    else if (charIndex >= lineLength[lineIndex]) {      
      lineIndex++;
      charIndex = 0;
      return nextChar();
    }   
    else if (str[lineIndex][charIndex] == '#') {      
      hashCheck = true;  
      while (hashCheck = true) {
        if (str[lineIndex][charIndex] == '#') { hashCheck = false; }        
        charIndex++;
        if (charIndex > lineLength[lineIndex]) {
          charIndex = 0;
          lineIndex++;
        }
      }
    }    
    else {
      ch = str[lineIndex][charIndex];
      charIndex++;
      return ch;            
    }   
    cout << "you shouldn't be here\n";
  return str[lineIndex][charIndex];
}

Token Lex::nextToken() { 
  if (charIndex == lineIndex && charIndex == 0) { ch = nextChar(); }        
  while (ch == ' ') { ch = nextChar(); }
  // cout << "CI: " << charIndex << endl;
  string build;
  int tempCharIndex = charIndex;  
  int tempLineIndex = lineIndex;
  build += ch;
  if (charIndex == lineIndex && charIndex == 0) { build = ""; }
  if (checkSet == true) {
    checkSet = false;   
    while (ch != ' ' && tempLineIndex == lineIndex) {
      ch = nextChar();
      if (ch != ' ' && tempLineIndex == lineIndex) 
        build += ch;        
    }
    idents[identCount] = build;
    identCount++;   
    return Token(IDENT, build, tempLineIndex, tempCharIndex);
  }  
  else if (isSpecialChar(ch)) {    
    switch(ch) {
    case '(':
      ch = nextChar();
      return Token(LPAREN, build, tempLineIndex, tempCharIndex);
    case ')':
    ch = nextChar();
      return Token(RPAREN, build, tempLineIndex, tempCharIndex);
    case '{':
    ch = nextChar();
      return Token(THEN, build, tempLineIndex, tempCharIndex);
    case '}':
    ch = nextChar();
      return Token(ENDIF, build, tempLineIndex, tempCharIndex);
    case '+':
    ch = nextChar();
      return Token(PLUS, build, tempLineIndex, tempCharIndex);
    case '-':
    ch = nextChar();
      return Token(MINUS, build, tempLineIndex, tempCharIndex);
    case '/':
    ch = nextChar();
      return Token(DIVIDE, build, tempLineIndex, tempCharIndex);
    case '*':
    ch = nextChar();
      return Token(TIMES, build, tempLineIndex, tempCharIndex);
    case '=':
      ch = nextChar();
      if (ch == '=') {      
        build += ch;
        ch = nextChar();        
        return Token(EQ, build, tempLineIndex, tempCharIndex);
      }
      else {

        return Token(ASSIGN, build, tempLineIndex, tempCharIndex);
      }
    case '>':
      ch = nextChar();
      if (ch == '=') {      
        build += ch;
        ch = nextChar();
        return Token(GE, build, tempLineIndex, tempCharIndex);
      }
      else return Token(GT, build, tempLineIndex, tempCharIndex);
    case '<':
      ch = nextChar();
      if (ch == '=') {                
        build += ch;
        ch = nextChar();
        return Token(LE, build, tempLineIndex, tempCharIndex);
      }
      else return Token(LT, build, tempLineIndex, tempCharIndex);
    case '!':
      ch = nextChar();
      if (ch == '=') {      
        build += ch;
        ch = nextChar();
        return Token(NE, build, tempLineIndex, tempCharIndex);
      }
      else return Token(ERROR, build, tempLineIndex, tempCharIndex);
    case '%':
    ch = nextChar();
      return Token(REM, build, tempLineIndex, tempCharIndex);
    case '&':
    ch = nextChar();
      return Token(AND, build, tempLineIndex, tempCharIndex);
    case '|':
    ch = nextChar();
      return Token(OR, build, tempLineIndex, tempCharIndex);
    default:
      return Token(ERROR, build, tempLineIndex, tempCharIndex);
    }
  }
  else if (isNum(ch)) {
    tempCharIndex = charIndex;
    while (ch != ' ' && tempLineIndex == lineIndex) {
      ch = nextChar();
      if (isSpecialChar(ch)) { 
        break;
      }
      if (ch != ' ' && tempLineIndex == lineIndex) 
        build += ch;      
    }   
    if (isNumFinal(build)) {
      if (build.find('.') != build.npos) 
        return Token(FLOATLIT, build, tempLineIndex, tempCharIndex);
      else return Token(INTLIT, build, tempLineIndex, tempCharIndex);
    }
    else return Token(ERROR, build, tempLineIndex, tempCharIndex);
  }
  else {
    tempCharIndex = charIndex;
    while (ch != ' ' && tempLineIndex == lineIndex) {     
      ch = nextChar(); 
      // cout << "ch: " << ch << endl;
      if (ch != ' ' && tempLineIndex == lineIndex) 
        //cout << "inserted: " << ch << endl;
        build += ch;
    }   
    if (build.compare("while") == 0)
      return Token(WHILE, build, tempLineIndex, tempCharIndex);
    else if (build.compare("if") == 0)
      return Token(IF, build, tempLineIndex, tempCharIndex);
    else if (build.compare("print") == 0)
      return Token(PRINT, build, tempLineIndex, tempCharIndex); 
    else if (build.compare("end") == 0)
      return Token(ENDOFFILE, build, tempLineIndex, tempCharIndex);
    else if (build.compare("else") == 0)
      return Token(ELSE, build, tempLineIndex, tempCharIndex);
    else if (build.compare("do") == 0)  { return Token(DO, build, tempLineIndex, tempCharIndex); }
    else if (build.compare("set") == 0) {
      checkSet = true;
      // cout << "CI: " << str[lineIndex] << endl;
      return Token(SET, build, tempLineIndex, tempCharIndex);
    }   
    else {
      for (int i = 0; i < identCount; ++i) {
        if (build.compare(idents[i]) == 0) { return Token(IDENT, build, tempLineIndex, tempCharIndex); }
      }
      cout << "build:" << build << ".\n"; 
      return Token(STRLIT, build, tempLineIndex, tempCharIndex);
    }
  }
}

4 个答案:

答案 0 :(得分:8)

除非您致电delete[],否则请勿致电new[]str是您班级中的一个静态大小的数组,您既不需要new[]也不需要delete[]

您的类完全由对象组成,这些对象将处理自己的清理,或者不需要清理,因此您的析构函数可以简单地为空。甚至不要声明它,在这种情况下编译器将为您提供正确的析构函数。

答案 1 :(得分:2)

str没有动态存储持续时间,但您尝试在析构函数中删除它。从析构函数中删除delete[] str

填写str时,您也没有进行任何边界检查。这可能会导致您覆盖其他成员变量,从而导致其他问题,并且可能是您遇到的故障的原因。

// tempSize and/or lineNum may be greater than 256
for (int i = 0; i < tempSize; ++i) {      
  str[lineNum][i] = temp[i];
  lineLength[lineNum] += 1;
}   

答案 2 :(得分:1)

你有

Lex::~Lex() { 
 delete [] str;
}
代码中的

,但str未分配堆。它是Lex

的数据成员

我相信最近调用的GCC g++ -Wall -g可能会警告你这个错误。

答案 3 :(得分:0)

好吧,因为你根本不需要删除str数组,它不是由你使用new创建的,所以你不需要调用delete

VS给了我: 警告C4154:删除数组表达式;转换为提供的指针