MixTr |
Отправлено: 25.11.2005, 20:34 |
|
Не зарегистрирован
|
Есть такая функция:
CODE |
String OpenData::OData(String FName, int Number)
{
ifstream file1;
char FN[100];
char str[80];
file1.open(strcpy(FN,FName.c_str()));
if (!file1) {return ("Error open file");}
TStringList *MyList = new TStringList;
int i=0;
while (!file1.eof())
{
file1.getline(str,sizeof(str));
MyList->Add(str);
i++;
}
return MyList->Strings[Number];
} |
Как можно возвратить весь список а не одну строчку:
return MyList->Strings[Number];
Пользуйтесь тэгами [CODE]!
Отредактировано Gedeon — 25/11/2005, 21:13 |
|
Admin |
Отправлено: 25.11.2005, 21:12 |
|
Владимир
Группа: Администратор
Сообщений: 1190
|
Наверное правильно будет создать
TStringList *MyList = new TStringList;
не в этой функции, а в вызывающей эту функцию программе,
а в функцию передавать указатель на этот TStringList
CODE |
TStringList *MyList = new TStringList;
try{
OData( MyList );
// ... выполняем некие действия с этими строчками
}__finally{
delete MyList; // освобождаем память
}
|
и соответственно OData() будет выглядеть примерно так
CODE |
void OpenData::OData(TStringList *MyList)
{
ifstream file1;
char FN[100];
char str[80];
file1.open(strcpy(FN,FName.c_str()));
if (!file1) {return ("Error open file");}
int i=0;
while (!file1.eof())
{
file1.getline(str,sizeof(str));
MyList->Add(str);
i++;
}
}
|
Только может еще можно упрастить весь этот код ?
Например
CODE |
TStringList *MyList = new TStringList;
MyList->LoadFromFile( FName );
// ... Выполняем какие-то действия со строчками
delete MyList; // освобождаем память
|
Отредактировано Admin — 25/11/2005, 21:13
|
|
Gedeon |
Отправлено: 25.11.2005, 21:16 |
|
Ветеран
Группа: Модератор
Сообщений: 1742
|
А что мешает возвратить
?
|
|
Admin |
Отправлено: 25.11.2005, 21:28 |
|
Владимир
Группа: Администратор
Сообщений: 1190
|
Все равно как-то не очень правильно — память
под StringList выделяет в функции, а освобождает
где и в какой момент ? Может в приведенном коде
ошибок это и не вызовет, но уже на грани ...
|
|
Gedeon |
Отправлено: 25.11.2005, 21:45 |
|
Ветеран
Группа: Модератор
Сообщений: 1742
|
Да, код веселый .
Память естественно надо освобождать, да и вообще назначение функции не понятно, создал где нужно StringList, загрузил из файла его же методом и работай.
а вот это что такое?
file1.open(strcpy(FN,FName.c_str()));
а это
file1.getline(str,sizeof(str));
и еще
if (!file1) {return ("Error open file");}
удобнее некуда обрабатывать текст, а не код ошибки
нахрена там i?
я только к коду присмотрелся, весело
|
|
Grigoriy |
Отправлено: 25.11.2005, 23:39 |
|
Мастер участка
Группа: Участник
Сообщений: 381
|
QUOTE (MixTr @ 25/11/2005, 20:34) |
Как можно возвратить весь список а не одну строчку:
return MyList->Strings[Number];
|
CODE |
TStringList* OpenData::OData(String FName, int Number)
{
ifstream file1;
char FN[100];
char str[80];
file1.open(strcpy(FN,FName.c_str()));
if (!file1) {return ("Error open file");}
TStringList *MyList = new TStringList;
while (!file1.eof())
{
file1.getline(str,sizeof(str));
MyList->Add(str);
i++;
}
return MyList;
} |
|
|
Konstantine |
Отправлено: 28.11.2005, 10:09 |
|
Мастер участка
Группа: Модератор
Сообщений: 545
|
Grigoriy, это неправильно... — обсуждалось выше — выделяется прамять в функции, а освобождается где???
|
|
Grigoriy |
Отправлено: 28.11.2005, 11:13 |
|
Мастер участка
Группа: Участник
Сообщений: 381
|
QUOTE (Konstantine @ 28/11/2005, 10:09) | Grigoriy, это неправильно... — обсуждалось выше — выделяется прамять в функции, а освобождается где??? |
А освобождается в другой функции.
То есть память выделяется в одной подпрограмме, а освобождается в той подпрограмме, которая вызвала вышеуказанную. Это так же как например, стандартная функция malloc выделяет память и возвращает указатель, но эта память освобождается другой функцией free.
|
|
** Admin |
Отправлено: 28.11.2005, 21:05 |
|
Не зарегистрирован
|
Grigory
Это понятно, но вы можете точно сказать — в какой именно момент
будет освобождена эта память ???
Повторюсь — Может в приведенном коде ошибок это и не вызовет, но уже на грани ...
Приведу пример — а если эту функцию я вызову 10000 раз — что будет
с памятью — утечка памяти ? Каждый раз будет выделяться
новая память и не освобождаться ?
Приведу пример:
CODE |
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
TStringList* ml;
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
String FName;
if(OpenDialog1->Execute()){
FName = OpenDialog1->FileName;
for(int i=0; i<10000; i++) ml = OData(FName);
}
ShowMessage(ml->Text);
}
//---------------------------------------------------------------------------
TStringList* TForm1::OData(String FName) // упростим код, оставив все — как в вашем примере — выделение памяти в функции и возврат
указателя из нее
{
TStringList *MyList = new TStringList;
MyList->LoadFromFile(FName);
return MyList;
}
void __fastcall TForm1::Button2Click(TObject *Sender)
{
ShowMessage(ml->Text);
}
//--------------------------------------------------------------------------- |
Попробуйте — запустите диспетчер задач, переключитесь
на вкладку — загрузка процессора и память и запустив программу
понаблюдайте за памятью ! Очень скоро ее не останется
и получите AV.
Куда проще как я писал выше.
Отредактировано Admin — 28/11/2005, 21:09 |
|
Grigoriy |
Отправлено: 28.11.2005, 23:21 |
|
Мастер участка
Группа: Участник
Сообщений: 381
|
QUOTE | Это понятно, но вы можете точно сказать — в какой именно момент
будет освобождена эта память ???
|
Когда эта память будет освобождаться — Это воля MixTr. Он должен решить этот вопрос. А я не задумываюсь об этом хотя бы потому, что незнаю полного содержания проблемы, которую должна решить программа, так как в первом сообщении обсуждалась всего одна из ее подпрограмм.
Могу только предупредить, что память, выделяемая подпрограммой
String OpenData::OData(String FName, int Number)
должна обязательно освобождаться.
QUOTE |
TStringList *MyList = new TStringList;
try{
OData( MyList );
// ... выполняем некие действия с этими строчками
}__finally{
delete MyList; // освобождаем память
}
|
Да, конечно, идея понятная, но :
1. В этом случае нужно постоянно заботится о конструировании объекта типа TStringList перед тем, как вызывать функцию OData.
2. Так можно использовать указатель MyList только в той функции, в которой он объявлен и не в какой другой без передачи указателя в качестве локального параметра.
QUOTE |
Повторюсь — Может в приведенном коде ошибок это и не вызовет, но уже на грани ...
|
Да, согласен, при работе с указателями нужно внимательно составлять алгоритм, например, во избежание того, чтобы во время освобождать ненужные блоки памяти.
QUOTE |
Приведу пример — а если эту функцию я вызову 10000 раз — что будет
с памятью — утечка памяти ? Каждый раз будет выделяться
новая память и не освобождаться ?
|
А зачем так нерационально расходовать память ?
CODE |
for(int i=0; i<10000; i++) ml = OData(FName);
|
ведь в этом случае вместо одного вызова OData(FName) используется аж 10000 вызовов и при том считывается одна и та же информация !
Аналогично я бы написал
CODE |
void* p;
for (int i=0;i<100000;i++){p=malloc(100000);};
|
и добавил, что при выполнении этого кода на персональном компьютере нехватит памяти.
Функцию void __fastcall TForm1::Button1Click(TObject *Sender)
правильно было бы оформить так
CODE |
void __fastcall TForm1::Button1Click(TObject *Sender)
{
String FName;
if(OpenDialog1->Execute()){
FName = OpenDialog1->FileName;
for(int i=0; i<10000; i++) {
ml = OData(FName);
ShowMessage(ml->Text);
delete ml;};
}
}
|
Отредактировано Grigoriy — 29/11/2005, 09:08
|
|
Asher |
Отправлено: 29.11.2005, 09:46 |
|
Мастер участка
Группа: Модератор
Сообщений: 550
|
Привет всем.
Возвращайте свой лист завернутым в auto_ptr.
|
|