Por que difftime() resulta em resultados diferentes ao usar ponteiro e não ponteiro de manipulação mktime?

StackOverflow https://stackoverflow.com//questions/25048439

  •  21-12-2019
  •  | 
  •  

Pergunta

eu tento usar

    difftime(time_t end, time_t mktime(start) ) 

para calcular a diferença entre dois tempos diferentes de duas maneiras diferentes.Só por curiosidade! E descobri que resulta em resultados diferentes, fracasso e sucesso.Eu não sei por que isso aconteceu?

Por que isso resulta em resultados diferentes em dois casos como segue?

    // Failure Case 1     when execution, segmentation fault
    time_t end;
    time(&end);

    struct tm * start;   // defining a pointer

    start->tm_hour = 0;
    start->tm_min  = 0;
    start->tm_sec  = 0;
    start->tm_year = 114;
    start->tm_mon  = 6;
    start->tm_mday = 29;

    double second = difftime(end, mktime(start) ); // where problem come from!

    // Success Case 2, with expected result
    time_t end;
    time(&end);       

    struct tm start;   // defining a non-pointer

    start.tm_hour = 0;
    start.tm_min  = 0;
    start.tm_sec  = 0;
    start.tm_year = 114;
    start.tm_mon  = 6;
    start.tm_mday = 29;

    double second = difftime(end, mktime( &start) );
Foi útil?

Solução

O caso original 1 não aloca memória e ambos os casos não limpam TODOS os campos do tm estrutura, que pode ser necessária para obter o resultado correto (e certamente é uma "boa prática").

Para resolver o Caso 1 em C, a melhor solução é usar calloc:

struct tm *start = calloc(1, sizeof(struct tm)); 

start->tm_year = 114;
start->tm_mon  = 6;
start->tm_mday = 29;

e então quando você não precisar mais do start valor, uso

free(start);

(Observe que como a estrutura é preenchida com zeros, você não precisa mais definir manualmente hora, min, seg)

Em C++, você usaria new em vez de:

tm *start = new tm(); 
...
// After it is finished. 
delete start

O parêntese vazio em tm() faz com que ele seja "preenchido com valores zero" após alocar a memória real.

A variante "Caso 2" é preferida, pois aloca o start variável na pilha.

O caso 1 é um tanto ruim, pois alocar memória para pequenas estruturas de dados (pequeno normalmente significa algo menor que cerca de 1 KB, mas depende do ambiente de execução real, um relógio com 64 KB de RAM pode ter requisitos mais rígidos do que uma máquina desktop com 16 GB de RAM , e um telefone celular estaria em algum lugar entre eles, dependendo do tipo de telefone).Existem pelo menos dois motivos para evitar alocações de memória "pequenas":

  1. É preciso mais memória, já que todos os alocadores conhecidos usam ALGUMA memória extra para controlar o "pedaço" real de memória alocada.
  2. Leva mais tempo porque new ou calloc são muito mais complexos do que a alocação na pilha (em máquinas típicas, a alocação de espaço na pilha leva de 1 a 2 instruções acima e além da mesma função, sem nenhuma variável, onde uma chamada para new ou {c,m}alloc pode ser meia dúzia apenas para a ligação e o mesmo novamente para delete ou free, e várias dezenas a alguns milhares de instruções dentro dessas funções de biblioteca - a duração do código depende muito de como ele é implementado e se o tempo de execução tem alguma "memória disponível" ou se uma chamada ao sistema operacional é necessária para "obter mais memória" também).E, claro, você precisa acompanhar a alocação e não “vazá-la”.[Existem soluções C++ para fazer isso também, mas já escrevi o suficiente nesta resposta para dificultar o acompanhamento]

Para o caso 2 você pode usar:

struct tm start = {}; 

(E novamente, você não precisa definir valores zero para hora, minuto e segundo)

Em C++ é correto omitir struct, desde struct tm { ... }; declaração no arquivo de cabeçalho relevante torna o nome tm representar a estrutura de qualquer maneira - isso se aplica a todos struct e class nomes - a única exceção é se o mesmo nome for usado de uma maneira diferente, por ex.existe uma função ou variável chamada tm no mesmo contexto - nesse caso o compilador apresentará algum erro dizendo "não entendo o que você quer dizer com tm aqui" [o texto exato varia dependendo de qual compilador é usado].

Como a pergunta original especifica AMBOS C e C++, tentei explicar

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top