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


Автор: Toohtik 12.4.2007, 20:33
Взялся  писать курсовой. Его задание написать прогу которая читает txt файлы и отображает информацию о нем (размер, количество букв, слов...) Интрефейс под Win32. Возник вопрос, стоит ли писать класс File в котором будет содератся инофрмация о файле и в котором можно будит считать/сохранить из файла или просто реализовать функциями?

И воторой:
Код

void File::fOpenFile(void)
{
    free(cText);                           //освободить память
    hFile =    CreateFile(buf,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);    
    DWORD b;                                //для хранения количества прочтенных байт
    iFileSize = GetFileSize(hFile,NULL);            //получения размера файла
    cText = (char*)calloc(iFileSize+1,sizeof(char));    //выделение под текст места                        
    ReadFile(hFile,cText,iFileSize,&b,NULL);
    fGetTextInformation();
    CloseHandle(hFile);
}

Обязателько ли перед тем как выделить новую, осводить старую и не лучше ли использваоть new delete?

 

Автор: fantast 12.4.2007, 20:42
Цитата(Toohtik @  12.4.2007,  20:33 Найти цитируемый пост)
Обязателько ли перед тем как выделить новую, осводить старую и не лучше ли использваоть new delete?

если ты не сделаешь free то просто затрешь старый указатель на ранее выделенную память, и впоследствии не сможешь ею воспользоваться или хотяб освободить, а новой выделенной памятью будешь пользоваться в полной мере. Можно конечно и не освобождать, но это приведет к утечке памяти. 
а new delete работает точно также, поэтому если и тут не освобождать, то результат будет идентичный
лично я не вижу между ними никаких принципиальных различий

Автор: console 12.4.2007, 20:45
new/delete - это для С++, calloc и прочая фень - СИ... 
Для твоего случая конечно лучше new/delete и я думаю реализовать класс лучше...
Цитата(Toohtik @  12.4.2007,  19:33 Найти цитируемый пост)
Обязателько ли перед тем как выделить новую, осводить старую

А вот это предложение ты объясни поподробнее... )))

Автор: fantast 12.4.2007, 20:45
Цитата
 стоит ли писать класс File


это только твое дело, но мне кажется если самые светлые умы программирования всетаки сделали такую замечательную штуку как класс,
ей грех не воспользоватья, программа станет намного нагляднее и красивее.

Автор: leniviy 12.4.2007, 20:46
alloc или new - это имхо без разницы, главное, не пытаться освободить память оператором delete, если вы её получили функцией calloc. new - более стандартный способ.
освобождать память надо, только не забудьте в конструкторе обнулить cText и проверять cText != NULL.

Автор: fantast 12.4.2007, 20:47
console
Цитата
конечно лучше new/delete


ну над этим можно и поспорить, 
что new/delete, что calloc/free, теже яйца, только в профиль

Автор: Toohtik 12.4.2007, 20:51
Ну имеется в виду что память особождать только после заверешения программы, а не каждый раз перед открытием файла.
Просто меня смущает вопрос, что если открыть текст размером 100 байт а потом к примеру 50 байт, то если не особождая перед откртием, память просто затрется, но в воздухе повиснит оставшиеся 50байт. Получается их уже нельзя не осободить не использовать, тоесть происходит утечка, я прав?

Автор: fantast 12.4.2007, 20:57
для этого если используешь calloc есть функция realloc, которая меняет длинну массива выделенного динамически.
ну а если new тогда надо каждый раз зачищать delete
вот
Цитата
тоесть происходит утечка, я прав?


да, ты прав. это никуда не годится

Автор: leniviy 12.4.2007, 21:00
это правда курсовая????

Автор: fantast 12.4.2007, 21:03
Цитата
Просто меня смущает вопрос, что если открыть текст размером 100 байт а потом к примеру 50 байт, то если не особождая перед откртием, память просто затрется, но в воздухе повиснит оставшиеся 50байт.


если ты напишешь:
Код

char *ch=new char[100];
ch=new char[50];


то у тебя ничего не затрется, просто ты выделишь 100 байт и вернешь на них указатель в ch,
а после этого выделишь еще 50 байт и опять запишешь на них указатель в ch.
получается что указатель на первые 100 байт просто потерялся и ты не сможешь получить к ним доступ потому что банально не знаешь где они находятся а ch будет указывать на 50 байт.
поэтому ты потеряешь не 50 байт а все 100.

Автор: Toohtik 12.4.2007, 21:19
А как воспользоватся функций realloc?
Да это курсовой 2 курса. Были и потруднее темы но там блин игры писать брррр ненавижуsmile

Автор: Mayk 12.4.2007, 21:24
М-ду calloc и new [] есть существенная разница --- 
1) calloc не вызвает конструкторы, в отличие от new[]
2) new[] не обнуляет выделенную память. В отличие от calloc


Автор: console 12.4.2007, 21:25
Пример с cplusplus.com: 

Код

include <stdio.h>
#include <stdlib.h>

int main ()
{
  int input,n;
  int count=0;
  int * numbers = NULL;

  do {
     printf ("Enter an integer value (0 to end): ");
     scanf ("%d", &input);
     count++;
     numbers = (int*) realloc (numbers, count * sizeof(int));
     if (numbers==NULL)
       { puts ("Error (re)allocating memory"); exit (1); }
     numbers[count-1]=input;
  } while (input!=0);

  printf ("Numbers entered: ");
  for (n=0;n<count;n++) printf ("%d ",numbers[n]);
  free (numbers);

  return 0;
}

Автор: fantast 12.4.2007, 21:27
Цитата(Toohtik @  12.4.2007,  21:19 Найти цитируемый пост)
брррр ненавижу

ну это ты зря
кажется так
void* realloc(void *mass,int size);
*mass - указатель на динамический массив (уже созданный при помощи функции malloc или calloc)
size - новый размер массива в байтах

функция возвращает новый указатель на динамический массив (в дльнейшем использовать именно его)


Автор: console 12.4.2007, 21:29
Как видим из примера с cplusplus.com в моем предыдущем посте, не обязательно перед этим резервировать память calloc'ом либо malloc'ом

Автор: fantast 12.4.2007, 21:32
Цитата
 не обязательно 


хм, моя училка по программированию меня жестко наколола  smile 

Автор: console 12.4.2007, 21:33
cplusplusDOTcom:


ptr (см в коде)

Цитата

Pointer to a memory block previously allocated with malloc, calloc or realloc to be reallocated.
If this is NULL, a new block is allocated and a pointer to it is returned by the function.


Указатель на блок памяти, зарезервированный malloc, calloc или realloc, необходимый для переопределения размера...
Если указатель нулевой, резервируется новый блок и функция realloc возвращает указатель на нее...

Автор: Toohtik 12.4.2007, 21:35
Я затронул эту тему из за того что в новокупленой книжке было написано что лучше использовать new/delete, так что Mayk, с тобой согласен.
Вот только не могу понять какой плюс от вызова конструктора при использовании new, объясните плиз!
console, как вообщем realloc пользоваться я знаю, т.к. курсовой я уже написал, а это думаю его немного улучшитьsmile А вот как изменить длину массива?
 


Автор: fantast 12.4.2007, 21:43
Цитата
А вот как изменить длину массива?


Код

char *ch=calloc(100,sizeof(char));
ch=realloc(ch,150*sizeof(char));


сначало ch указывал на 100 байт, а ты его (массив) расширели до 150 байт

Автор: Toohtik 12.4.2007, 21:46
а что произойдет если размер указать не 150, а 50, утечка памяти?

Автор: fantast 12.4.2007, 21:48
не лишнее просто отрежется

Автор: console 12.4.2007, 21:49
У тебя урежется массив... и исчезнут данные, которые были в диапазоне [51;100]

Автор: Toohtik 12.4.2007, 21:57
Тогда получается, что функцию free можно использовать 1 раз при завершении программы?
И воторой вопрос немного не потеме: где лучше писать пользовательские функции. Т.е. у меня есть модуль под класс и надо еще несколько функций для общего использования в проге. Надо ли их выносить в отдельный cpp и если да то надо ли создавать h файл для заголовка функций?

Автор: fantast 12.4.2007, 22:05
 дело твое, я б сказал индивидуальное
к чему больше душа лежит там и описывай свои функции

если проект пишет несколько людей то да, удобнее это не объединять в один cpp, а каждый делает свою часть кода, запихивает в свой cpp, а дальше дело компилятора (если конечно все пространство имен у них были верно согласованы)


Цитата(Toohtik @  12.4.2007,  21:57 Найти цитируемый пост)
Тогда получается, что функцию free можно использовать 1 раз при завершении программы?

если ты используешь free то динамически выделенный массив перестает существовать, а указатель, что раньше указывал на массив будет указывать на случайное место в памяти, другими словами он будет пуст. если есть необходимость можно его опять пустить в дело, например опять выделить динамический массив, или использовать его как обычный указатель, вобщем дело хозяйское

Автор: console 12.4.2007, 22:06
Можно по разному... лучше конечно вынести в отдельный .cpp и .h

Автор: nickless 12.4.2007, 22:38
Цитата(Toohtik @  12.4.2007,  20:35 Найти цитируемый пост)
Вот только не могу понять какой плюс от вызова конструктора при использовании new, объясните плиз!

Если выделять память под сложные объекты, то нужен вызов конструктора для их инициализации, или прийдётся извращатся через дополнительный вызов какого-нибудь метода, который делает то же, что делает new + конструктор.
Например:
Код
#include <iostream>
#include <cstdlib>
using namespace std;

class A
{
public:
    A() : mP( new double[200] ) { cout << "A()" << endl; };
    ~A() { delete[] mP; cout << "~A()" << endl; }
    void test() { for ( int i = 0; i < 200; i++ ) { mP[i] = 1234.56789; } }
private:
    double * mP;
};

int main()
{
    // new / delete
    cout << "test new/delete" << endl;
    A * bla = new A;
    bla->test(); // ok
    delete bla;

    // calloc / free
    cout << "test calloc / free" << endl;
    A * blub = (A*)calloc( 1, sizeof(A) );
    blub->test(); // ups...
    free( blub );

    return 0;
}

Получаем:
Код
$ g++ -Wall -Wextra -pedantic -pipe -o bla bla.cpp
$ ./bla
test new/delete
A()
~A()
test calloc / free
Segmentation fault

Автор: Toohtik 16.4.2007, 00:09
Возникла следующая проблемма. Все работает на ура, но при выходе из програмы выскакивает ошибка. Я это связываю с действиями деструктора, т.к. если его закоментировать, то все ок
Код

class File
{
public:
    ~File();                                //деструктор    
    char* cText;                            // указатель на текст из файла    
    ...
    
private:
          ...

};
File::~File()
{
    free(cText);
}

Автор: Daevaorn 16.4.2007, 00:21
Цитата(Toohtik @  16.4.2007,  01:09 Найти цитируемый пост)
Возникла следующая проблемма. Все работает на ура, но при выходе из програмы выскакивает ошибка. Я это связываю с действиями деструктора, т.к. если его закоментировать, то все ок

проверяй свой код на правильность работы с памятью. выходы за переделы массива и т.п.

Добавлено через 36 секунд
Цитата(nickless @  12.4.2007,  23:38 Найти цитируемый пост)
или прийдётся извращатся через дополнительный вызов какого-нибудь метода

Ну можно позвать и конструктор вручную.

Автор: JackYF 16.4.2007, 16:54
Цитата(Daevaorn @  16.4.2007,  00:21 Найти цитируемый пост)
Ну можно позвать и конструктор вручную. 

Хм... по стандарту?

Автор: Daevaorn 16.4.2007, 17:35
Цитата(JackYF @  16.4.2007,  17:54 Найти цитируемый пост)
Хм... по стандарту?

абсолютно

Автор: nickless 16.4.2007, 17:39
Цитата(Daevaorn @  15.4.2007,  23:21 Найти цитируемый пост)
Ну можно позвать и конструктор вручную

А зачем, если можно просто использовать new?

Автор: JackYF 16.4.2007, 21:19
Цитата(Daevaorn @  16.4.2007,  17:35 Найти цитируемый пост)
абсолютно 


Могу, конечно, зарыться головой в стандарт. Но, может быть, ты просто покажешь пример?

Автор: Daevaorn 16.4.2007, 21:24
Цитата(JackYF @  16.4.2007,  22:19 Найти цитируемый пост)
Могу, конечно, зарыться головой в стандарт. Но, может быть, ты просто покажешь пример?

placement new ещё никто не отменял, поэтому создать объект можно на любой памяти. не понимаю, что у тебя вызвало затруднение.

Автор: JackYF 16.4.2007, 21:33
Цитата(Daevaorn @  16.4.2007,  21:24 Найти цитируемый пост)
placement new ещё никто не отменял, поэтому создать объект можно на любой памяти. не понимаю, что у тебя вызвало затруднение. 


Э, нет smile Про placement new и мы знаем smile Нам вызов конструктора подавай. Например, в уже созданном объекте  smile 

Автор: Daevaorn 16.4.2007, 21:55
Цитата(JackYF @  16.4.2007,  22:33 Найти цитируемый пост)
 Про placement new и мы знаем  Нам вызов конструктора подавай. 

тебе не кажется это соседство странным?)
Код

{
   Foo bar(777);
   new( &bar ) Foo(666); //oops
   //...
}

Автор: console 16.4.2007, 22:46
Цитата(Daevaorn @  16.4.2007,  20:55 Найти цитируемый пост)
{   Foo bar(777);   new( &bar ) Foo(666); //oops   //...}


ЧТО ЭТО????!!!!  smile 

Автор: JackYF 16.4.2007, 23:57
Цитата(Daevaorn @  16.4.2007,  21:55 Найти цитируемый пост)
тебе не кажется это соседство странным?)


Да, когда шел домой и было время подумать, дошло, что ты хотел сказать.
Что ж, спасибо. Да, действительно, и так можно smile

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