简体   繁体   English

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

[英]What does my destructor need to be in this function?

My program executes fine, except at the end, when I debug it, it's getting a segmentation error after calling my destructor. 我的程序执行得很好,除了最后,当我调试它时,它在调用析构函数后出现分段错误。 I'm not sure what the cause of the issue is. 我不确定是什么原因造成的。 I've posted 2 of the relevant files. 我已经发布了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 is below: 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 is here. 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);
    }
  }
}

Don't call delete[] unless you called new[] . 除非您调用new[]否则不要调用delete[] new[] str is a statically sized array in your class, you need neither new[] nor delete[] for it. str在您的类中是一个静态大小的数组,因此不需要new[]delete[]

Your class consists entirely of objects which will either handle their own cleanup, or need no cleanup, so your destructor can simply be empty. 您的类完全由对象组成,这些对象要么处理自己的清理,要么不需要清理,因此析构函数可以简单地为空。 Don't even declare it, and the compiler will provide the correct destructor for you in this case. 甚至不用声明它,在这种情况下,编译器将为您提供正确的析构函数。

str does not have dynamic storage duration but you are trying to delete it in the destructor. str没有动态存储持续时间,但是您试图在析构函数中将其删除。 Remove delete[] str from your destructor. 从析构函数中删除delete[] str

You also are not doing any bounds checking when you fill str . 当您填充str时,您也没有进行任何边界检查。 This may cause you to overwrite other member variables causing additional problems and is likely the cause of the fault you are experiencing. 这可能会导致您覆盖其他成员变量,从而导致其他问题,并且很可能是您遇到错误的原因。

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

You have 你有

Lex::~Lex() { 
 delete [] str;
}

in your code, but str is not heap allocated. 在您的代码中,但str未分配堆。 It is a data member of your Lex class 它是Lex类的数据成员

I believe a recent GCC invoked as g++ -Wall -g would probably have warned you about that mistake. 我相信,最近使用g++ -Wall -g调用的GCC可能会警告您有关该错误的信息。

Well, cause you don't need to delete the str array at all, it's not created by you using new so you don't need to call delete . 好吧,因为您根本不需要删除str数组,它不是由您使用new创建的,因此您不需要调用delete

VS gives me : warning C4154: deletion of an array expression; VS给我:警告C4154:删除数组表达式; conversion to pointer supplied 转换为提供的指针

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM