Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
T_e_n_Jl_bl_u
3 / 3 / 1
Регистрация: 27.07.2017
Сообщений: 52
#1

Очистка динамической памяти - C++

27.07.2017, 16:46. Просмотров 383. Ответов 12

Добрый день, у меня такой вопрос:
Есть функция принимающая на вход три аргумента: указатель на область памяти, выделенную с помощью оператора new[], размер области (size) и новый размер (new_size). Функция должна выделить память размера new_size, скопировать в нее данные из переданной области памяти, освободить старую область памяти и вернуть выделенную область памяти нового размера со скопированными данными (задание со stepic.org, только я его перевел в void для тестов).
Проблема такая, я написал код,
C++
1
2
3
4
5
6
7
8
9
10
void resize(const char *str, int size, int new_size)
{
  char * m = new char [new_size]; 
  if(new_size<size){
           for(int i=0; i<new_size; i++){*m=*str; *m++; *str++;}
 }else{
           for(int i=0; i<size; i++){*m=*str; *m++; *str++;}
 }
  delete[] str;
}
Проблема такая: выполнение подвисает на строке
C++
1
delete[] str;
Пожалуйста, объясните, что может быть не так.
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
27.07.2017, 16:46
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Очистка динамической памяти (C++):

Выделение и очистка динамической памяти
Добрый день. Никак не могу найти информацию по следующему вопросу. Допустим...

Очистка динамической памяти в структуре
И снова здравствуйте. Столкнулся с проблемой. Есть задача - написать программу...

Очистка динамической памяти очереди
Доброго времени суток! Я вот думаю-думаю, но докумекать не могу. Я пишу...

очистка памяти
в данном случае деструктор очистит всё, или нет? #include &quot;base.h&quot; #include...

Очистка памяти
Вот сделал лабу и все работает отлично, но осталось последнее new выделяет...

Очистка памяти
Как правильно очистить память в массиве классов Вот код конструктора,...

12
Azazel-San
Mental handicap
123 / 123 / 65
Регистрация: 24.11.2015
Сообщений: 819
Завершенные тесты: 1
27.07.2017, 16:50 #2
delete str;
0
GeFacle
Рэмбо комнатный
95 / 95 / 99
Регистрация: 05.03.2017
Сообщений: 505
Завершенные тесты: 4
27.07.2017, 16:52 #3
C++
1
2
3
4
5
6
7
char* temp=new char[size];
temp=str;
delete[] str;
str=new char[new_size];
for (int i=0;i<size;i++)
{ str[i]=temp[i]; }
delete[] temp;
Добавлено через 1 минуту
Azazel-San, просто delete это вроде для одного объекта, а тут массив символов -> нужен delete[]
1
Azazel-San
Mental handicap
123 / 123 / 65
Регистрация: 24.11.2015
Сообщений: 819
Завершенные тесты: 1
27.07.2017, 16:55 #4
GeFacle, да, все верно, я что-то подумал что там string
0
DrOffset
7518 / 4514 / 1097
Регистрация: 30.01.2014
Сообщений: 7,362
27.07.2017, 16:56 #5
T_e_n_Jl_bl_u,
В delete[] должен попасть тот же самый адрес, что возвращала new[].
Твой код:
C++
1
2
3
4
5
6
7
8
9
10
11
void resize(const char *str, int size, int new_size)
{
  const char * old = str;
  char * m = new char [new_size]; 
  if(new_size<size){
           for(int i=0; i<new_size; i++){*m=*str; m++; str++;}
  }else{
           for(int i=0; i<size; i++){*m=*str; m++; str++;}
  }
  delete[] old;
}
PS. Разыменования при инкременте не нужны.
0
T_e_n_Jl_bl_u
3 / 3 / 1
Регистрация: 27.07.2017
Сообщений: 52
27.07.2017, 17:04  [ТС] #6
Код то работает, но уж очень долго, и тестер не принимает, пишет "#1. Runtime error:...", просто без этой строки все работает во много раз быстрее, хотелось бы знать, почему.
Очистка динамической памяти

Очистка динамической памяти
0
DrOffset
7518 / 4514 / 1097
Регистрация: 30.01.2014
Сообщений: 7,362
27.07.2017, 17:05 #7
Цитата Сообщение от GeFacle Посмотреть сообщение
C++
1
2
3
char* temp=new char[size]; 
temp=str;
//.....
Не надо так делать.
0
DrOffset
7518 / 4514 / 1097
Регистрация: 30.01.2014
Сообщений: 7,362
27.07.2017, 17:10 #8
Цитата Сообщение от T_e_n_Jl_bl_u Посмотреть сообщение
Код то работает, но уж очень долго, и тестер не принимает, пишет "#1. Runtime error:...", просто без этой строки все работает во много раз быстрее, хотелось бы знать, почему.
Потому что копировать побайтно в цикле - неэффективно.
Можно сделать так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <cstdio>
#include <cstring>
 
char * resize(char const * p, size_t oldLen, size_t newLen)
{
    char * nBuf = new char[newLen];
    if(p)
    {
        std::memcpy(nBuf, p, std::min(oldLen, newLen));
    }
    delete[] p;
    return nBuf;
}
0
GeFacle
Рэмбо комнатный
95 / 95 / 99
Регистрация: 05.03.2017
Сообщений: 505
Завершенные тесты: 4
27.07.2017, 17:10 #9
DrOffset, почему?
0
DrOffset
7518 / 4514 / 1097
Регистрация: 30.01.2014
Сообщений: 7,362
27.07.2017, 17:20 #10
Цитата Сообщение от GeFacle Посмотреть сообщение
почему?
Ну вот выделил ты память, тебе вернули указатель. А следом ты его сразу же затер значением другого указателя str. Все, получили утечку, на ровном месте. Зачем это?

Добавлено через 7 минут
Цитата Сообщение от T_e_n_Jl_bl_u Посмотреть сообщение
пишет "#1. Runtime error:...",
Так а чего ты не исправил свой код, как я показал в #5?
Runtime error у тебя от того, что ты в delete[] засунул указатель проинкрементированный на new_size или size позиций. Это же не тот же самый адрес, который вернула new[], вот менеджер кучи и ругается, что ты ему неучтенный адрес пытаешься скормить.
0
T_e_n_Jl_bl_u
3 / 3 / 1
Регистрация: 27.07.2017
Сообщений: 52
27.07.2017, 17:22  [ТС] #11
Цитата Сообщение от DrOffset Посмотреть сообщение
Потому что копировать побайтно в цикле - неэффективно.
Можно сделать так:
Сделал по-твоему примеру, быстрее не стало
Очистка динамической памяти
0
DrOffset
7518 / 4514 / 1097
Регистрация: 30.01.2014
Сообщений: 7,362
27.07.2017, 17:50 #12
Лучший ответ Сообщение было отмечено SatanaXIII как решение

Решение

Цитата Сообщение от T_e_n_Jl_bl_u Посмотреть сообщение
быстрее не стало
Судя по скрину, ты творишь какую-то дичь. Зачем в функцию resize отдавать адрес данных в стеке? Так делать ни в коем случае нельзя. То, что у тебя в итоге только лишь тормозит, не самое худшее проявление после такого безобразия.
Вот тебе полный, компилируемый код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <cstdio>
#include <cstring>
#include <algorithm>
 
char * resize(char const * p, size_t oldLen, size_t newLen)
{
    char * nBuf = new char[newLen];
    if(p)
    {
        std::memcpy(nBuf, p, std::min(oldLen, newLen));
    }
    delete[] p;
    return nBuf;
}
 
int main()
{
    char const src[] = "hey what's going on?";
    
    char * buf = new char[sizeof(src)];
    std::strcpy(buf, src);
    
    buf = resize(buf, sizeof(src), 25);
    
    for(size_t i = 0; i < 25; ++i)
    {
        std::printf("%c-", buf[i]);
    }
    delete[] buf;
}
Вот тут я его запустил: http://rextester.com/YYMGW9631, обрати внимание на время исполнения.

Добавлено через 14 минут
Тоже самое, если взять твой первоначальный вариант и нормально его переписать, чтобы освобождалось по нужному адресу и возвращало из функции тоже новый, правильный адрес (а не проинкрементированный до конца последовательности), то тоже все будет работать:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
char * resize(const char *str, int size, int new_size)
{
  char * m = new char [new_size]; 
  if(new_size < size)
  {
      for(int i = 0; i < new_size; i++)
      { 
          m[i] = str[i]; 
      }
  }
  else
  {
      for(int i = 0; i < size; i++)
      {
          m[i] = str[i];
      }
  }
  delete[] str;
  return m;
}
Правда все-таки медленее, чем с memcpy. Как уже говорил, копирование побайтно в цикле - неэффективно.
1
T_e_n_Jl_bl_u
3 / 3 / 1
Регистрация: 27.07.2017
Сообщений: 52
27.07.2017, 18:06  [ТС] #13
Всё, разобрался, всем спасибо.
0
27.07.2017, 18:06
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
27.07.2017, 18:06
Привет! Вот еще темы с решениями:

Очистка памяти
Цель: Написать программу, которая читает текст из файла и записывает в новый...

Очистка памяти
Подскажите пожалуйста что не так делаю, создаю массив лейблов: TLabel...

Очистка памяти
При выполнении программы, память приложения растёт, а она должна быть...

Выделение динамической памяти
Доброго времени суток! я начинающий программист, столкнулась с такой...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru