powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / утечка памяти
5 сообщений из 5, страница 1 из 1
утечка памяти
    #39031196
polin11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Взял листинг кода из книги Стивен Прата Язык программирования С++.
Меня терзают смутные сомнения нет ли здесь утечки памяти, указатель,
определенный в функции buildstr в куче, не очищается в ней. Очищается
указатель ps на результат функции. Адреса &ps!=&pstr, указатели указывают на
на одну область. Хочу в своей программе сделать похожий подход, функция
возвращает указатель на символьный массив

Код: plaintext
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.
#include<iostream>
using namespace std;
char* buildstr(char c, int n);
int main()
{
   int times;
   char ch;
   cout<<"Enter a character";
   cin>>ch;
   cout<<"Enter an integer";
   cin>>times;
   char* ps=buildstr(ch, times); 
   cout<<ps <<"\n";
   delete [] ps;                  //высвобождение памяти
   ps=buildstr('+', 20);          // повторное использование указателя
   cout<<ps <<"DONE" <<ps <<"\n";
   delete [] ps;                   //высвобождение памяти
   return 0;
}

char* buildstr(char c, int n)
{
   char* pstr=new char[n+1];
   pstr[n]='\0';
   while(n-->0)
        pstr[n]=c;
   return pstr;
}
...
Рейтинг: 0 / 0
утечка памяти
    #39031204
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
polin11Меня терзают смутные сомнения нет ли здесь утечки памяти Нету. Данный код корректен.

Но так делать действительно не очень хорошо. В документации на функцию buildstr мы конечно напишем что она возвращает новый кусок памяти который надо освобождать отдельно, но никто не гарантирует что мы не забудем это сделать. И вот тогда уже будет утечка.


Поэтому, обычно в таких случаях память выделяют в вызывающей функции и в вызываемую отдают указатель на подготовленный буфер. Получается типа:
Код: plaintext
1.
2.
3.
4.
p = new char[times+1];
fillstring(p, ch, times); 
cout << p;
delete [] p;
...
Рейтинг: 0 / 0
утечка памяти
    #39031819
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
polin11Взял листинг кода из книги Стивен Прата Язык программирования С++.
Меня терзают смутные сомнения нет ли здесь утечки памяти, указатель,
определенный в функции buildstr в куче, не очищается в ней.


Так функция создаёт новую строку и возвращает её. Если её удалить, то возвращать нечего будет.
Код предполагает, что вызывающая функция должна освободить память после использования строки.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
char* buildstr(char c, int n);

char* buildstr(char c, int n)
{
   char* pstr=new char[n+1];
   pstr[n]='\0';
   while(n-->0)
        pstr[n]=c;
   return pstr;
}




Поглядим теперь на вызывающий код.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
#include<iostream>
using namespace std;
char* buildstr(char c, int n);
int main()
{
   int times;
   char ch;
   cout<<"Enter a character";
   cin>>ch;
   cout<<"Enter an integer";
   cin>>times;
   char* ps=buildstr(ch, times); // ВЫДЕЛЕНИЕ
   cout<<ps <<"\n";
   delete [] ps;                  // ОСВОБОЖДЕНИЕ
   ps=buildstr('+', 20);          // ВЫДЕЛЕНИЕ ( в том, что повторно используется указатель ps для работы с другой строкой 
                                          // нет ничего плохого, указатели собственно для этого и придуманы, чтобы работать с разными переменными, на которые они указывают
   cout<<ps <<"DONE" <<ps <<"\n";
   delete [] ps;                   //ОСВОБОЖДЕНИЕ
   return 0;
}



Всё корректно.
Заметь, что вызывается не
Код: plaintext
1.
delete ps;


а
Код: plaintext
1.
delete [] ps;



как и положено по стандарту.

авторОчищается
указатель ps на результат функции.

Ничего плохого.


авторАдреса &ps!=&pstr, указатели указывают на
на одну область.


Ну, я не понимаю, что ты не понимаешь.
&ps != &pstr -- да, это две разные переменные типа "указатель", их адреса поэтому
разные. Но они указывают (в какой-то момент времени) на один и тот же массив символов (строку).

Если ещё остались вопросы, задавай, но подробнее.
...
Рейтинг: 0 / 0
утечка памяти
    #39031827
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
White Owl
Поэтому, обычно в таких случаях память выделяют в вызывающей функции и в вызываемую отдают указатель на подготовленный буфер.



Это не так. "Обычно" здесь не прокатывает. Тут нет "обычно".
Зависит всё от ситуации, назначения кода и соглашений о программировании в конкретном проекте.

А вот что точно в современном С++ уже не принято (хотя это просто традиция и общие идиомы), так это возвращать
голые указатели на динамическую память.
Тут надо было бы использовать либо smart_pointer-ы, либо вообще использовать std::vector или std::string.

Но это видимо учебный пример, т.к. такой функционал точно есть в std::string и он в рельной программе мало кому будет интересен.
...
Рейтинг: 0 / 0
утечка памяти
    #39033575
BagaBaga
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Управление "голой" памятью очень полезно для собственного понимания. Но в большинстве проектов нет необходимости в "сырой" работе с памятью - если только вы не пишете очередной аналог "менеджера ресурсов" навроде умных указателей.

Соглашения о кодировании - хорошая штука. Плохо, что компиляторы их не читают. Поэтому, когда кто-нибудь забудет, ничем не помогут. А забыть можно просто - просто "запутавшись" в области видимости и понадеявшись на "соседа". Но современный С++ (С++11.С++14/С++17) позволяет во многих случаях переложить на плечи компилятора эту проблему (код отработает для С++14/С++17, для С++11 нужно "подсказать" возвращаемый тип функции):
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
#include <iostream>
#include <memory>
using namespace std;

auto bstr(const char c, int n)
{
    std::unique_ptr<char[], 
                    std::function<void(const char*const)>> 
	    str( new char[n+1], 
	         [](const char*const ch){delete [] ch;}
	       );	
	str[n]='\0';
	for( ; n--; )
		str[n] = c;
	
	return str;
}

int main() {
	// your code goes here
	auto s = bstr('a',10);
	cout << s.get() ;
	return 0;
}
...
Рейтинг: 0 / 0
5 сообщений из 5, страница 1 из 1
Форумы / C++ [игнор отключен] [закрыт для гостей] / утечка памяти
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]