В программе — нигде.
Да и вообще у Вас там выход за пределы выделенной памяти
int len = strlen(s);
st.str = new char[len]; //Выделили память под len символов
strcpy(st.str, s); //Скопировали в приемник len символов + завершающий 0
Память, выделенная при помощи new, освобождается только при помощи delete или после завершения программы.
Юрий
Правильно, porshe! Применение new должно сопровождаться вызовом delete. Повторю вопрос.
ВОПРОС: Где в данной программе нужно вызвать операцию delete?
(Выход за пределы массива исправлен)
#include <iostream>
#include <cstring>
struct stringy{
char * str;
int ct;
};
void set(stringy & st, char * s);
void show(const stringy & st, int n = 1);
void show(const char * test, int n = 1);
int main()
{
stringy beany;
char testing[] = "Reality isn't what it used to be.";
set(beany, testing);
show(beany);
show(beany, 2);
testing[0] = 'D';
testing[1] = 'u';
show(testing);
show(testing, 3);
show("Done!");
return 0;
}
void set(stringy & st, char * s)
{
const int len = strlen(s);
st.str = new char[len + 1];
strcpy(st.str, s);
st.ct = len;
}
void show(const stringy & st, int n)
{
while(n--)
std::cout << st.str << std::endl;
}
void show(const char * test, int n)
{
while(n--)
std::cout << test << std::endl;
}
А я даже не знал, что это было задание, я думал это был вопрос :)
Где в данной программе нужно вызвать операцию delete?
Вообще, её здесь негде применять, дабы не потерять значение beany. Но уж если сильно хочется, то можно создать функцию _free(), которая освободит память, и присвоит beany.str = NULL.
P.S.: А почему бы не сделать класс? Будет ведь удобнее, и освобождением будет заниматься деструктор.
(0) В исходном варианте кода память освобождается только при завершении программы. Для того, что бы освободить память в программе, перед return 0 надо вставить оператор delete [] beany.str;. Но это не очень красивый вариант.
(1) Захват, перераспределение и освобождение ресурсов должно происходить на одном уровне абстракции. Это [должно быть!] общеизвестное правило. Если уровень абстракции функции, как в данном случае, то вариант от Croessmah как раз удовлетворяет этому правилу. Если уровень абстракции класс, то работа с ресурсами должна происходить на уровне методов класса.
(2) Вариант от Croessmah фактически реализует абстракцию на уровне класса. void init(stringy & st ) — конструктор, void release(stringy & st ) — деструктор, void set(stringy & st, char * s) — метод-сеттер или оператор присваивания, void show(const stringy & st, int n) — почти метод-геттер. Конечно, что бы привести этот код к виду нормального класса, требуется серьёзная доработка (для того, что бы во всех ситуациях класс (экземпляр класса) работал ожидаемым образом.
Кстати, хорошая тема для новой «разминки для мозгов»: аккуратно написать класс, реализующий строку со счётчиком (или «строка в стиле Pascal») без использования STL и других библиотек. Примечание: строка со счётчиком НЕ завершается '\0'.
Croessmah, почему всё так пессимистично? Тема вполне исчерпаемая, если не усложнять себе задачу абсолютной переносимостью кода в сочетании с абсолютной эффективностью, поддержкой многобайтовых кодировок и неограниченным объёмом строки.
В данном случае, смысл «разминки» заключался бы в аккуратном написании класса с динамическим захватом и освобождением ресурсов (памяти) и с минимальной функциональностью. Ключевое слово «аккуратно». Задачка достаточно простая, но есть подводные камни. В плане повышения собственного скилла — полезно.
Внимание! Это довольно старый топик, посты в него не попадут в новые, и их никто не увидит. Пишите пост, если хотите просто дополнить топик, а чтобы задать новый вопрос — начните новый.
Доброго времени суток всем!!!
Имею вот такой вопрос. Вот код
ВОПРОС: Где освобождается память, выделенная в функции
void set(stringy & st, char * s)
?В программе — нигде.
Да и вообще у Вас там выход за пределы выделенной памяти
Но память то выделена при помощи new?
Память, выделенная при помощи
new
, освобождается только при помощиdelete
или после завершения программы.Правильно, porshe! Применение
new
должно сопровождаться вызовомdelete
. Повторю вопрос.ВОПРОС: Где в данной программе нужно вызвать операцию delete?
(Выход за пределы массива исправлен)
А я даже не знал, что это было задание, я думал это был вопрос :)
Вообще, её здесь негде применять, дабы не потерять значение
beany
. Но уж если сильно хочется, то можно создать функцию_free()
, которая освободит память, и присвоитbeany.str = NULL
.P.S.: А почему бы не сделать класс? Будет ведь удобнее, и освобождением будет заниматься деструктор.
Чёрт, понял в чём тут фишка.
Освобождать память нужно в начале функции
set
, что бы избежать утечки памяти.То есть как то так:
При условии, что пустая
st.str = NULL
( можно задать в конструкторе, например ).можно без if.
То есть, если попытаться освободить память по адресу
0
, то ничего не произойдёт?Ничего.
Ребята, программа не компилится ???
Да и не логично удалять в функции
void set(stringy & st, char * s)
память при помощиdelete
перед тем как функция выделяет память при помощиnew
.логично.
А как ещё избежать утечки памяти?
делать нормальный класс. А еще лучше пользоваться готовым :)
я про это уже писал выше :)
Резюмируя вышесказанное...
(0) В исходном варианте кода память освобождается только при завершении программы. Для того, что бы освободить память в программе, перед
return 0
надо вставить операторdelete [] beany.str;
. Но это не очень красивый вариант.(1) Захват, перераспределение и освобождение ресурсов должно происходить на одном уровне абстракции. Это [должно быть!] общеизвестное правило. Если уровень абстракции функции, как в данном случае, то вариант от Croessmah как раз удовлетворяет этому правилу. Если уровень абстракции класс, то работа с ресурсами должна происходить на уровне методов класса.
(2) Вариант от Croessmah фактически реализует абстракцию на уровне класса.
void init(stringy & st )
— конструктор,void release(stringy & st )
— деструктор,void set(stringy & st, char * s)
— метод-сеттер или оператор присваивания,void show(const stringy & st, int n)
— почти метод-геттер. Конечно, что бы привести этот код к виду нормального класса, требуется серьёзная доработка (для того, что бы во всех ситуациях класс (экземпляр класса) работал ожидаемым образом.Кстати, хорошая тема для новой «разминки для мозгов»: аккуратно написать класс, реализующий строку со счётчиком (или «строка в стиле Pascal») без использования STL и других библиотек. Примечание: строка со счётчиком НЕ завершается '\0'.
увы, эта тема бесконечна и не имеет решения :)
Череп, а подробнее, что за строка со счетчиком?
И если есть время посмотри мой первый класс :)
Croessmah, почему всё так пессимистично? Тема вполне исчерпаемая, если не усложнять себе задачу абсолютной переносимостью кода в сочетании с абсолютной эффективностью, поддержкой многобайтовых кодировок и неограниченным объёмом строки.
В данном случае, смысл «разминки» заключался бы в аккуратном написании класса с динамическим захватом и освобождением ресурсов (памяти) и с минимальной функциональностью. Ключевое слово «аккуратно». Задачка достаточно простая, но есть подводные камни. В плане повышения собственного скилла — полезно.