Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > нужно ли удалять указатель на символьный массив с


Автор: polin11 8.8.2015, 00:44
Подскажите, программа состоит из 2 функций (main и fun), программа меняет значение указателя на символьный массив созданный в динамически распределяемой памяти. 
Программ меняет символьный массив "abc" на "cba" ошибок нет. Вопрос в другом, нужно ли удалять указатель из кучи в функции main или fun, не произойдет ли утечка памяти,
не становиться ли указатель str_f из функции fun "диким" при завершении функции fun??? При попытке удалить указатель delete str_f или delete[] str_f, при выполнении программы выходит ошибка. 




Код

#include "stdafx.h"
#include <iostream>
#include <stdlib.h>
#include <conio.h>
#include <stdio.h>
#include <windows.h>

using namespace std;
char* fun()
{
   char* str_f=new char[5];
   ZeroMemory(str_f, 5);
   str_f="cba";
   /* delete str_f;  нужно ли удалять указатель массив char из динамически распределяемой памяти. При выполнении выходит ошибка */
   return str_f; 
}
int _tmain(int argc, _TCHAR* argv[])
{
    
    int n=5;
    char* str=new char[5];
    ZeroMemory(str, 5);
    str="abc";
    cout<<str <<endl;
    str=fun();
    cout<<str <<endl;
    /* delete[] str; нужно ли удалять указатель массив char из динамически распределяемой памяти. При выполнении выходит ошибка */
    cout<<str;
    getch();
    return 0;
    
}

Автор: feodorv 8.8.2015, 08:17
Цитата(polin11 @  8.8.2015,  00:44 Найти цитируемый пост)
char* fun()
{
   char* str_f=new char[5];
   ZeroMemory(str_f, 5);
   /* str_f="cba"; */
   delete str_f;  /* нужно ли удалять указатель массив char из динамически распределяемой памяти. При выполнении выходит ошибка */
   return str_f
}

Вот подумайте сами. Вы высвободите запрошенный массив символов, а указатель на него вернёте из функции. На что будет указывать этот указатель? Он, конечно, будет указывать куда-тов память процесса, но куда? Неизвестно. Указатель стал невалидным, использовать в дальнейшем его категорически нельзя. В этом смысле такой код мало чем отличается от такого:
Код
char* fun()
{
   char str_f[5];
   ZeroMemory(str_f, 5);
   memcpy( str_f, "cba", sizeof("cba"));
   return str_f; 
}


ЗЫ Массив высвобождается через delete [] ..., а не просто delete.


Но что Вы делаете в коде. После выделения участка памяти под массив, Вы изменяете значение указателя:
Цитата(polin11 @  8.8.2015,  00:44 Найти цитируемый пост)
   str_f="cba";

присваивая ему значение, указывающее на константную строчку (этот код никоим образом не копирует строчку "cba" в выделенный массив). В результате у Вас указатель str_f указывает на константную строчку, а не на выделенный участок памяти. Высвовождение невыделенного и приводит к ошибке. Тупо это проверьте, выведя на экран значение указателя str_f до присвоения константной строчкой и после. Увидите, что значение указателя круто изменилось.

Автор: TarasProger 12.8.2015, 10:49
polin11, утечка произошла уже в 25-й строке: в 21-й память по указателю была выделена, а адрес, где именно выделена, записано в указателе и нигде больше, потом в 25-й строке указателю присвиваеется значение функции, которая тоже что то выделила и вернула адрес, где именно выделила. Так как указатель поменял свою значение при этом присваивании, то старое значение с адресом выдения в 21-й строке потерялось. Раз ты по этому указателю выделял память, то прежде чем менять его значение, надо память освободить. Совсем другое дело 
Код
char *p;
char *i;
p=new char [256];
i=p;
do
{
 ++i; /*Память выделена по p, а меняется i, это разные указатели, адрес всего блока выделенной
 памяти в p остаётся, i же используется для перебора. В этом случае ничего освобождать не нужно*/
} while ((i-p)<256);
, но и тогда p надо освободить после использования. Если это локальная автоматическая переменная функции и значение этой переменной наружу не выдаётся, то в любом месте функции до её завершения, но не раньше, чем блок выделенной памяти станет не нужен. Если глобальная, то до завершения программы, но опять таки после того, как выделенный блок станет не нужен, а если это переменная, значение которой выдаётся наружу, то где то в вызывающем коде, но опять таки до его завершения, но не раньше, чем сам выделенный блок станет не нужен.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)