2015-01-20 6 views
-2

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

Моя проблема в том, что я не могу освободить эту строку, если Visual Studio не ударил точку останова для меня. Я могу заставить его работать с кодом, который у меня есть ниже (не освобождая вообще от рогальной строки) d =, но не может ли это вызвать утечку памяти?

Спасибо за вашу помощь заранее.

#include <iostream> 
using namespace std; 

class SmartString{ 
    private: 
     char* str; 
    public: 
     SmartString () 
     { 
      str = NULL; 
     } 
     SmartString (char *str){ 
      int length = 0; 
      int copy_index = 0; 
      while(str[length] != '\0') 
      { 
       length++; 
      } 
      length++; 
      char * copy; 
      copy = (char*)malloc(sizeof(char) * length); 
      copy = new char[length]; 
      while(copy_index < length) 
      { 
       copy[copy_index] = str[copy_index]; 
       cout << str[copy_index]; 
       copy_index++; 
      } 
      this -> str = copy; 
     } 
     ~ SmartString() 
     { 
      if(str != NULL) 
      { 
       delete str; 
       free(str); 
      } 
     } 
     void ShowString() 
     { 
      cout << "[" << str << "]"; 
     } 
     int Size() 
     { 
      if(str == NULL) 
       return 0; 
      else 
      { 
       int i = 0; 
       while(str[i] != '\0') 
       { 
        i++; 
       } 
       i++; 
       return i; 
      } 
     } 
     **void Trim() 
     { 
      int counter = 0; 
      while (str[counter] == ' ' && counter < Size()) 
      { 
       counter++; 
      }  
      int new_length = Size() - (counter + 1); 
      char * temp; 
      temp = (char*) malloc(sizeof(char) * new_length); 
      temp = new char[new_length]; 
      int counter_2 = 0; 
      while(counter_2 < Size()) 
      { 
       temp[counter_2] = str[counter_2 + counter]; 
       counter_2++; 
      } 
      str = temp; 
     }** 
}; 

int main() 
{ 
    char *str; 
    str = " Hello"; 
    SmartString * s = new SmartString(str); 
    str = "Change"; 
    (*s).Trim(); 
    (*s).ShowString(); 

    system("Pause"); 
} 
+1

Не используйте 'malloc' в C++ (кроме того, что вы делаете * оба * и память утечки и ** затем ** двойное удаление). Кроме того, должно быть 'delete [] str;' поскольку вы 'new []'. – crashmstr

+1

Почему существует 'новый', непосредственно следуя за' malloc', с результатами обоих присваивается 'copy'? – Michael

+0

@crashmstr: Да, но, к сожалению, 'realloc()' работает только с 'malloc()'. Поэтому 'malloc()' представляется мне совершенно разумным, особенно если вам нужно «обрезать массив», как говорит OP, которого он хочет. –

ответ

0

Вы не использовали 'delete' в своей основной функции для освобождения переменной указателя 's', так что метод деструктора вашего класса SmartString никогда не вызывался. В вашем втором методе constrcutor вам я дважды назначил переменную «copy», где она не нужна. И также вы ошибаетесь в методе «Trim».

В вашем методе деструктора вы должны удалить оператор free(str);, потому что оператор delete str; освободит 'str'. Поэтому нет необходимости снимать дважды.

malloc - Выделяет запрошенную память и возвращает указатель на нее.
new X; - Выполняйте то же самое, но также вызывайте метод конструктора, если X является классом или структурой после выделения.
new X[] - Выделяет динамический массив с запрошенной памятью и возвращает указатель на него.

free - Отменяет выделенную ранее память.
delete - Выполняет то же самое, но также вызывает метод деструктора, если X является классом или структурой после освобождения.
delete[] - освобождает ранее выделенный динамический массив памяти.

new и delete стандартное распределение памяти и открепление реализации языка C++, где malloc и free является стандартом распределения памяти и открепление функция языка C.

Здесь я переписать свой 'Обрезать' метод:

void Trim() 
    { 
     int counter = 0; 
     while (str[counter] == ' ' && counter < Size()) 
     { 
      counter++; 
     } 
     int new_length = Size() - (counter + 1); 
     char * temp; 
     // There is no need to allocate twice 
     //temp = (char*) malloc(sizeof(char) * new_length); 
     temp = new char[new_length+1]; 
     int counter_2 = 0; 
     while(counter_2 < //Size() (Here is your big mistake. You should not use 'Size()' here) 
          new_length 
         ) 
     { 
      temp[counter_2] = str[counter_2 + counter]; 
      counter_2++; 
     } 
     temp[counter_2] = 0; 

     str = temp; 
    } 

И deallocating, вы должны использовать 'Удалить', как это:

int main() 
{ 
    char *str; 
    str = " Hello"; 
    SmartString * s = new SmartString(str); 
    str = "Change"; 
    (*s).Trim(); 
    (*s).ShowString(); 

    // use delete to deallocate a pointer 
    delete s; 

    system("pause"); 
} 
+0

Моя ошибка. У меня создалось впечатление, что free() и delete делали разные вещи - явно нет. Я изучил java, затем python в этом порядке, поэтому я не привык играть с распределением памяти. Спасибо за вашу помощь. – user2019645

+0

@ user2019645, все в порядке, вас также приветствуют. –

+0

Я получаю ОБОРОННУЮ КОРРУПЦИЮ, когда я делаю предложенные вами изменения. Только если я запустил и функцию Trim(), и освобождение SmartString s вызывает эту ошибку. Я еще раз посмотрю на свой код, но я подумал, что должен сообщить вам. – user2019645

0

Я вижу три разумных подхода к этому.

Можно было бы изменить существующую строку на месте. Найдите позицию первого непространственного символа, затем скопируйте оттуда до конца строки в позиции, начиная с первого элемента строки. Это нельзя применить к строковому литералу (или вы получите неопределенное поведение).

Во-вторых, нужно выделить новый буфер и скопировать данные, которые вы хотите сохранить в этом буфере. В этом случае вы, вероятно, делаете не хотите попробовать изменить оригинал (и, особенно, вы не хотите пытаться освободить его данные).

Третий должен был (в основном) повторить реализацию класса примерно как std::string, который всегда выделяет буфер определенным образом, поэтому он «знает», как безопасно манипулировать этим буфером. В этом случае вы могли бы/имели конструктор для создания объекта из строкового литерала, поэтому к моменту запуска вашей функции он будет (даже пытаться) манипулировать такими объектами и никогда не сможет случайно попытаться манипулировать/модифицировать что-то как строковый литерал.

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