реклама на сайте
подробности

 
 
> функция получения даты, на линуксе
romez777
сообщение Dec 13 2005, 09:40
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 292
Регистрация: 9-11-04
Пользователь №: 1 077



Приветствую.
Написал простую функцию (работаю под линуксом) возвращающую текущую дату, все бы ноормально но одна немаловажная проблема - утечка памяти. Потому как не могу в функци вызвать free(d), тогда нечего возвращать. Я уже совсем туплю, не знаю как обойти это smile.gif Нужна рекомендация

char* get_date(void)
{
time_t curtime;
struct tm *loctime;
char *d;

if ( !(d = malloc(9)) )
return NULL;

curtime = time(NULL); /* get сurrent time */
loctime = localtime(&curtime); /* convert to localtime representation */
strftime(d, 9, "%m/%d/%y", loctime);

return d;
}

Заранее благодарю!
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Olej
сообщение Dec 16 2005, 19:48
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 351
Регистрация: 11-09-05
Из: Харьков
Пользователь №: 8 458



Цитата
Конечно, разговор о стиле программирования это немного smile.gif bb-offtopic.gif (и мои замечания тоже), тем более он разный в зависимости от использования/неиспользования операционной системы, иногда и конкретной ОС, условий задачи (например, условие реентерабельности get_date()) и т.п.


Этот вопрос - это обсуждение сугубо не стиля программирования, а вопросов написания кода, свободного от скрытых ошибок, которые потом можно выявлять годами... Стиль программирования - это когда споры идут до хрипоты какой из эквивалентных фрагментов кода "правильный", а какой "ущербный":

Код
if( ... ) {
   cout << "terminal error";
   return( EXIT_FAILURE );
};


или

Код
if( ... ) cout << "terminal error", exit( EXIT_FAILURE );


Цитата
Ответ мой и zaratustra - это как надо бы, когда операционной системы точно нет (хотя и присутствуют функции динамического выделения памяти).


Функция malloc() - это API stdlib, в не зависимости от среды выполнения, и должна обеспечиваться любой совместимой С-системой, если таковая хочет нею считаться wink.gif, ... а если нет - то кто же ей доктор wink.gif.

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


- нет, копия, выделенная в стеке будет жить гораздо дольше wink.gif ... перезаписи её в стеке ... потому что перезаписи просто не будет! Если вы помните, стандарт С ISO/IEC 9899 1999 (называемый ANSI C 99) окончательно стандартизовал возврат любого сколь угодно сложной структуриры как результата выполнения функци ... раньше это было: "... это можно - это нельзя, ... здесь селёдку заворачивали(с) ...". Как это может происходить? Смотрим такой фрагмент (я для чистоты эксперимента - использую pure C а не C++):

Код
typedef struct { char d[ 20 ]; } X; // sizeof( X ) = 20
. . .
struct X func1( struct X Y ) {
   return Y;
};
. . .
void func2( void ) {
...
   struct X Y = func( X );
};


- сколько стека будет выделено при вызове func1? ответ: 40 байт - для области возврата + области копии параметров;
- в каком порядке они будут заталкиваться в стек? ответ: именно в таком, как сказано выше: область возврата + копии параметров + локальные переменные (если они есть - у нас нет);
- сколько копирований (байт?) будет при вызове-возврате? ответ: 3 (60 байт) - копирование параметра - копирование в область возврата - копирование присваивания;
- как и кем будет освобождаться стек? это уже интереснее, для это придётся вспомнить соглашения о вызовах некоторых языковых средств, например:

- PASCAL (BASIC, FORTRAN, ADA, OBERON, MODULA2): параметры заталкиваются в стек слева-направо, сама процедура должна восстановить стек перед return;
- C/C++ (PROLOG): параметры заталкиваются в стек справа-налево, вызывающий код должен восстановить стек после return;
- STDCALL (WIN32): параметны заталкиваются как С, а стек освобождается как PASCAL (Господи, это ж надо такое придумать!);
- WATCOM: первые (слева-направо) параметры грузятся в регистры EAX, EDX, EBX, ECX (сколько влезет ), а уж остальные заталкиваются в стек справа-налево как С;

Так вот - код вызывающей единицы С/С++ свернёт область стека после выполнения, но не область возврата структурного результата. Эта область остаётся распределённой как и область локальных переменных вызывающей единицы. Вопрос - когда же она освободится? - тогда же, когда и локальные переменные вызвавшей единицы - при выходе за область видимости вызывающей единицы (именно её завершении).

А чтобы не быть голословным, я вам продемонстрирую ассемблерный код, сгенерированный в подобном случае компилятором GCC 2.95 (ведь исходный вопрос был о Linux?):

Код
#define SIZE 1024   // только для степени 2 и простоты разбора
struct A { char B[ SIZE ]; } C;

struct A POW( struct A E ) { return E; };

int main( void ) {
   struct A D = POW( C );
   return 0;
};



И вот что из него получается:

Код
    
POW:
   pushl %ebp
   movl %esp,%ebp
   pushl %edi
   pushl %esi
   movl 8(%ebp),%eax
   movl %eax,%edi
   leal 12(%ebp),%esi
   cld
   movl $256,%ecx
   rep
   movsl
   movl %eax,%eax
   leal -8(%ebp),%esp
   popl %esi
   popl %edi
   leave
   ret $4

main:
   pushl %ebp
   movl %esp,%ebp
   subl $1040,%esp
   pushl %edi
   pushl %esi
   leal -1024(%ebp),%eax
   addl $-12,%esp
   addl $-1024,%esp
   movl %esp,%edi
   movl $C,%esi
   cld
   movl $256,%ecx
   rep
   movsl
   pushl %eax
   call POW
   addl $1036,%esp
   xorl %eax,%eax
   leal -1048(%ebp),%esp
   popl %esi
   popl %edi
   leave
   ret

   .comm   C,1024,32


Можете убедиться:
- структура из 1024 байт перед вызовом побайтно (у компилятора хватило ума сделать это 4-х байтными словами) копируется в стек, который "прогибается" вниз на 1024;
- возвращаемая структура также копируется в место в стеке, которое "бронируется" вызывающим кодом при завершении вызова.

P.S. Проу прощения за многословность, но такие вещи - проще не объясняются wink.gif.
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 29th July 2025 - 10:02
Рейтинг@Mail.ru


Страница сгенерированна за 0.01394 секунд с 7
ELECTRONIX ©2004-2016