Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.94/47: Рейтинг темы: голосов - 47, средняя оценка - 4.94
4 / 4 / 1
Регистрация: 27.07.2017
Сообщений: 54

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

27.07.2017, 16:46. Показов 8863. Ответов 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)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
27.07.2017, 16:46
Ответы с готовыми решениями:

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

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

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

12
Mental handicap
 Аватар для Azazel-San
1246 / 624 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
27.07.2017, 16:50
delete str;
0
Рэмбо комнатный
 Аватар для GeFacle
103 / 103 / 99
Регистрация: 05.03.2017
Сообщений: 511
27.07.2017, 16:52
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
Mental handicap
 Аватар для Azazel-San
1246 / 624 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
27.07.2017, 16:55
GeFacle, да, все верно, я что-то подумал что там string
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
27.07.2017, 16:56
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
4 / 4 / 1
Регистрация: 27.07.2017
Сообщений: 54
27.07.2017, 17:04  [ТС]
Код то работает, но уж очень долго, и тестер не принимает, пишет "#1. Runtime error:...", просто без этой строки все работает во много раз быстрее, хотелось бы знать, почему.


0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
27.07.2017, 17:05
Цитата Сообщение от GeFacle Посмотреть сообщение
C++
1
2
3
char* temp=new char[size]; 
temp=str;
//.....
Не надо так делать.
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
27.07.2017, 17:10
Цитата Сообщение от 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
103 / 103 / 99
Регистрация: 05.03.2017
Сообщений: 511
27.07.2017, 17:10
DrOffset, почему?
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
27.07.2017, 17:20
Цитата Сообщение от GeFacle Посмотреть сообщение
почему?
Ну вот выделил ты память, тебе вернули указатель. А следом ты его сразу же затер значением другого указателя str. Все, получили утечку, на ровном месте. Зачем это?

Добавлено через 7 минут
Цитата Сообщение от T_e_n_Jl_bl_u Посмотреть сообщение
пишет "#1. Runtime error:...",
Так а чего ты не исправил свой код, как я показал в #5?
Runtime error у тебя от того, что ты в delete[] засунул указатель проинкрементированный на new_size или size позиций. Это же не тот же самый адрес, который вернула new[], вот менеджер кучи и ругается, что ты ему неучтенный адрес пытаешься скормить.
0
4 / 4 / 1
Регистрация: 27.07.2017
Сообщений: 54
27.07.2017, 17:22  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
Потому что копировать побайтно в цикле - неэффективно.
Можно сделать так:
Сделал по-твоему примеру, быстрее не стало
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
27.07.2017, 17:50
Лучший ответ Сообщение было отмечено 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
4 / 4 / 1
Регистрация: 27.07.2017
Сообщений: 54
27.07.2017, 18:06  [ТС]
Всё, разобрался, всем спасибо.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
27.07.2017, 18:06
Помогаю со студенческими работами здесь

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

Очистка памяти
При выполнении программы, память приложения растёт, а она должна быть неизменной. int main() { setlocale(LC_ALL,...

очистка памяти
при запуск программы сама собой создаётся точка останова в строке 59. И дальше программа идти не хочет (даже инструментами отладки). //...

Очистка памяти
Как правильно очистить память в массиве классов Вот код конструктора, выделяющего память, и деструктора. Выдает ошибку в самом конце...

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


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

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru