2013-12-07 3 views
0

Я пытаюсь избавиться от утечек памяти в моем коде, но в любом случае я пытаюсь разыменовать указатели, это дает ошибку.Как удалить массив указателей в C++?

Код выглядит следующим образом:

ехр [] объявляется следующим образом в абстрактном классе Expression с конкретными подклассами: Binary, Constant и Бревенчатые следующим образом: статическое выражение * ехр []; который затем устанавливается в NULL в исходном файле выражения: Выражение * Выражение :: exp [] = {NULL};

Когда я закомментировать удаления б, удалить л и удалить со, программа работает нормально, но я подозреваю, что это оставляет утечку памяти

int main(void) 
    { 

     char userInput='j'; 

     while (userInput != 'q' && userInput != 'Q') 
     {  
     cout <<endl<<"Menu:" << endl<<"r - Reset the PC"<<endl<<"x - Enter a new value for register x"<<endl<<"y - Enter a new value for register y"<<endl<<"z - Enter a new value for register x"<<endl<<"s - Step by step execution"<<endl<<"e - Complete execution"<<endl<<"d - Display expressions"<<endl<<"q - Quit"<<endl; 
      cin >> userInput; 

      //Reset condition 
      if (userInput == 'r' || userInput == 'R') 
      { 
       debugPos=0; 
       //Opening file and reading it line by line 
       ifstream test("program.txt"); 
       string line; 
       while (getline(test, line)) 
       { 
        //Removing spaces from the string 
        std::remove(line.begin(), line.end(), ' '); 
        //Check if it is a log type statement and create an object of Log if it is 
        if(line[2]=='l' || line[2]=='L') 
        { 
         Log *l = new Log(line); 
         Expression::exp[Expression::count]= l; 
         Expression::count++; 
         delete l; 

        } 

        //Check if it is a binary type statement and create an object of Binary if it is 
        else if(line[2]=='x' || line[2]=='y' || line[2]=='z' || line[2]=='X' || line[2]=='Y' || line[2]=='Z') 
        { 
         Binary *b = new Binary(line); 
         Expression::exp[Expression::count]= b; 
         Expression::count++; 
         delete b; 

        } 
        //Else create an object of Constant type 
        else 
        { 
         Constant *co = new Constant(line); 
         Expression::exp[Expression::count]= co; 
         Expression::count++; 
         delete co; 

        } 

       } 
       test.close(); 

       cout<<endl<<"The expressions are read from the file"<<endl; 

      } 


      //Complete execution 
      else if (userInput == 'e' || userInput == 'E') 
      { 
       Expression::nExecute(); 
       cout<<endl<<"Value of X: "<<Expression::X<<endl<<"Value of Y: "<<Expression::Y<<endl<<"Value of Z: "<<Expression::Z<<endl; 
      } 


      //Quit condition 
      else if (userInput == 'q' || userInput == 'Q') 
      { 
       cout<<endl<<"Thanks for using the calculator"<<endl; 
       break; 
      } 

      else 
      { 
       cout<<endl<<"Choose from the menu please"<<endl; 
      } 
     } 
     return 0; 
    } 

Кроме того, в состоянии сброса, я пытаюсь сбросить указатели в NULL, так что я могу начать читать новые выражения из файла, но я не в состоянии установить массив, чтобы указать на NULL

+1

Если вы уверены, что вам нужно указатели, использовать смарт-указатели. – chris

+1

@chris Или «если вы уверены, что вам нужны указатели, используйте« вектор ». : P –

+0

Посмотрите функции 'toupper' и' tolower', поэтому вам не нужно сравнивать буквы дважды. –

ответ

0

Лучше:

Expression::exp.emplace_back(make_unique<Log>(line)); 
               // ^^ new Log(line) is hidden inside here 

и так далее, с

std::vector<unique_ptr<Expression>> exp; 

Тогда память будет освобождена, когда элементы будут удалены из вектора. И это безопасно.

Expression::count больше не потребуется, так как вы можете написать Expression::exp.size()

3

Вы получаете ошибки из-за этого

Constant *co = new Constant(line); 
Expression::exp[Expression::count]= co; 
Expression::count++; 
delete co; 

Yo u выделите память, поместите указатель на эту ячейку памяти в массив, затем отпустите эту память, поэтому в следующий раз, когда вы попытаетесь разыменовать указатель, хранящийся в вашем массиве, вы получаете доступ к свободной памяти. Если вам нужно, чтобы они сохранились, удалите их только после того, как вы закончите.

+0

Но я помещаю их в массив и после того, как я закончил использовать их. Могу я просто сказать delete [] exp. Это должно освободить память, верно? –

+0

Проблема в том, что delete [] освободит память, выделенную для массива, но ваш массив содержит указатели на другую выделенную память. Как только вы удалите указатели на объекты, которые вы создаете, вы не сможете получить к ним доступ через этот указатель. Они становятся болтливыми указателями. В вашем случае я не вижу преимущества в использовании указателей. Как предложили другие, рассмотрите возможность использования 'vector ' или 'vector ' и т. Д. Если вы ДОЛЖНЫ иметь указатели, используйте другой тип умного указателя, как предлагает другой ответ. – mathematician1975

+0

Кажется, что вы неправильно понимаете разницу между удалением самого массива и освобождением памяти, которую вы выделяете своим указателям, с помощью «новых» вызовов. Удаление массива указателей просто удалит ARRAY, он не освободит память, на которую указывает каждый указатель в массиве. Тогда это будет утечка памяти, если вы забыли освободить каждый указатель. В настоящее время вы делаете обратное - вы освобождаете память после добавления указателя на массив, поэтому вы, скорее всего, получите segfaults при попытке разыменовать эти указатели позже. – mathematician1975

Смежные вопросы