Pagina 1 di 1

GCC 3.3.6 vs GCC 4.2 - time()

Inviato: ven 17 apr 2009, 22:41
da Calzo
Ciao a tutti.
La domanda è: quale compilatore è meglio e/o cosa è cambiato tra i compilatori in oggetto?

Questa domanda la pongo perchè recentemente mi è capitato di portare alcuni vecchi programmi di esempio da un sistema ad un altro e di ricompilarli. Premetto che il sistema su cui li avevo scritti (che per altro è quello che uso tutt'ora) è una SlackWare 10.2 con compilatore gcc 3.3.6.
I programmi (o meglio il programma visto che è solo uno che da il problema) l'ho portato sotto Mint 6 e ricompilato. Il programma molto semplificato è il seguente:

Codice: Seleziona tutto

/* Assurdo.c: */
#include <stdio.h>
#include <stdlib.h>
int main() {
        int x;

        srand(time());
        printf("%i\n", (int)rand());
        return 0;
}
Il problema stà nella funzione time(). Questo programma sotto Slackware 10.2 funziona perfettamente, mentre sotto Mint 6 (gcc-4.3.2) genera un Segmentation Fault. Anche se la cosa mi è sembrata molto strana, ho letto il man di quelle 3 funzioni scritte nel programma ed effettivamente c'è scritto che time() richiede un puntatore in ingresso, oppure si metta NULL, cosa che io non ho fatto. A questo punto le domande che mi sono posto sono:

1. Perchè in SlackWare 10.2 funziona senza passare nessun parametro?
2. Perchè in sia in Slack che in Mint il compilatore non mi dice che manca un parametro? e perchè se scrivo time(&x, &x, &x) non mi dice che di parametri ce ne sono troppi?
3. Cosa cambia nel codice effettivo?

Bene: mentre alle prime domande non ho risposta, alla terza ho disassemblato il codice del del programma con time(). Il risultato è stato questo:

Codice: Seleziona tutto

Mint 6:
0x0804eaa0 <time+0>:	push   %ebp
0x0804eaa1 <time+1>:	mov    %esp,%ebp
0x0804eaa3 <time+3>:	mov    0x8(%ebp),%edx
0x0804eaa6 <time+6>:	push   %ebx
0x0804eaa7 <time+7>:	xor    %ebx,%ebx
0x0804eaa9 <time+9>:	mov    $0xd,%eax
0x0804eaae <time+14>:	int    $0x80
0x0804eab0 <time+16>:	test   %edx,%edx
0x0804eab2 <time+18>:	je     0x804eab6 <time+22>
0x0804eab4 <time+20>:	mov    %eax,(%edx)
0x0804eab6 <time+22>:	pop    %ebx
0x0804eab7 <time+23>:	pop    %ebp
0x0804eab8 <time+24>:	ret 
time() viene chiamata nel main senza salvare nessun parametro nello stack. Quindi alla riga +20 del codice appena postato è ovvio che crasha perchè va a scrivere in un indirizzo di memoria che al 99,9% non è NULL e quindi "je" (riga +18) non verrà mai eseguito.
Ma cosa succede allora in SlackWare 10.2? Bhè il codice è così:

Codice: Seleziona tutto

SlackWare:
    0x0804e1a0 <time+0>:    mov    %ebx,%edx
    0x0804e1a2 <time+2>:    mov    0x4(%esp),%ebx
    0x0804e1a6 <time+6>:    mov    $0xd,%eax
    0x0804e1ab <time+11>:   int    $0x80
    0x0804e1ad <time+13>:   mov    %edx,%ebx
    0x0804e1af <time+15>:   ret
A parte che è strutturalemente diverso, questo codice non creerà mai problemi. Ed inoltre sono 6 istruzioni contro le 14 di prima!!

Quindi ora riformulo la domanda iniziale: Perchè un compilatore + vecchio mi crea del codice più snello e (a mio dire) robusto, mentre il compilatore più nuovo mi genera codice meno ottimizzato? è cambiato qualche cosa a livello di librerie o di compilatore che non so?

Non so se sono stato chiaro, ma ad ogni modo grazie a tutti in anticipo x le eventuali spiegazioni :)

PS: Stavo per insultare Mint pesantemente insieme a ubuntu e a tutte le sue derivate, quando purtroppo tramite un conoscente ho provato a compilare il programma sotto SlackWare 12.2 e il problama c'è anche lì :cry:

Re: GCC 3.3.6 vs GCC 4.2 - time()

Inviato: sab 18 apr 2009, 10:21
da lamarozzo
In generale il passaggio dalla serie 3 a quella 4 di GCC ha portato molti cambiamenti strutturali nel compilatore, praticamente tutti positivi (l'aumento di prestazioni è veramente notevole). Il nuovo compilatore è però molto più rigido riguardo agli standard e cose che prima venivano tollerate ora non lo sono più.

Ad esempio, il tuo codice mi sembra che usi time in modo sbagliato (a meno che non ci sia una funzione time anche in stdlib.h).
Innanzitutto includi la libreria time.h e poi

Codice: Seleziona tutto

#include <time.h>
...
time_t tempo;
(void)time(&tempo);
srand((unsigned long int)tempo);
...
Prova a vedere se così le cose si aggiustano. Inoltre stai compilando con l'opzione -Wall? Un uso improprio di time salterebbe subito fuori.

Ciao.

Re: GCC 3.3.6 vs GCC 4.2 - time()

Inviato: sab 18 apr 2009, 11:46
da Mario Vanoni
Kernel statico con gcc 4.3.3 funziona,
ma molti programmi compilati con gcc 3.3.6 vanno in TILT,
ricompilandoli con gcc 4.3.3, peggio, crash'ano.

IMVHO anche le libraries (glibc ecc.) vanno prima ricompilate.

Tornato pentito a gcc 3.3.6 di Slackware 12.2.

Re: GCC 3.3.6 vs GCC 4.2 - time()

Inviato: sab 18 apr 2009, 15:40
da Calzo
lamarozzo ha scritto:In generale il passaggio dalla serie 3 a quella 4 di GCC ha portato molti cambiamenti [...] tutti positivi (l'aumento di prestazioni è veramente notevole). Il nuovo compilatore è però molto più rigido riguardo agli standard e cose che prima venivano tollerate ora non lo sono più.
Infatti anche io sapevo questo, e proprio per questo mi aspettavo che il compilatore mi segnalasse qualche cosa, ma nulla.

Ad ogni modo ho provato a compilare il programma con lemodifiche da te segnalate ed effettivamente torna tutto, ossia il compilatore mi dice che c'è qualche cosa che non va se invoco time() senza e parametri. Quindi ora funziona tutto.
Disassemblando il codice di time(), non vi sono differenze. Insomma: è chiaro che se uno scrivesse software come si deve e non come faccio io, le cose tornerebbero senza problemi :D
Mario Vanoni ha scritto:Kernel statico con gcc 4.3.3 funziona, [...]
IMVHO anche le libraries (glibc ecc.) vanno prima ricompilate.
Non ho capito cosa intendi per kernel "statico" ( :oops: ), però anche secondo me è meglio ricompilare anche le glibc.

Grazie
bye

Re: GCC 3.3.6 vs GCC 4.2 - time()

Inviato: sab 18 apr 2009, 16:40
da Mario Vanoni
Calzo ha scritto: Non ho capito cosa intendi per kernel "statico"
[ ] Enable loadable module support
e solo make bzImage

Re: GCC 3.3.6 vs GCC 4.2 - time()

Inviato: sab 18 apr 2009, 17:06
da Calzo
Mario Vanoni ha scritto: [ ] Enable loadable module support
e solo make bzImage
A ok, scusa, avevo pensato un'altra cosa.
Comunque hai detto che ti funziona in quel caso? Bene, ma adesso devo capire perchè 8)

grazie

Re: GCC 3.3.6 vs GCC 4.2 - time()

Inviato: sab 18 apr 2009, 17:12
da Mario Vanoni
Calzo ha scritto:
Mario Vanoni ha scritto: [ ] Enable loadable module support
e solo make bzImage
A ok, scusa, avevo pensato un'altra cosa.
Comunque hai detto che ti funziona in quel caso? Bene, ma adesso devo capire perchè 8)
Il kernel non usa glibc & co., e` autosufficiente.

Re: GCC 3.3.6 vs GCC 4.2 - time()

Inviato: sab 18 apr 2009, 22:44
da Luci0
Mario Vanoni ha scritto:
Calzo ha scritto: Non ho capito cosa intendi per kernel "statico"
[ ] Enable loadable module support
e solo make bzImage
Offtopic: Forse il termine più idoneo é ... kernel monolitico :-)

Ma forse kernel non modulare é forse anche meglio ...

Re: GCC 3.3.6 vs GCC 4.2 - time()

Inviato: dom 19 apr 2009, 10:56
da Mario Vanoni
Luci0 ha scritto:
Mario Vanoni ha scritto:
Calzo ha scritto: Non ho capito cosa intendi per kernel "statico"
[ ] Enable loadable module support
e solo make bzImage
Offtopic: Forse il termine più idoneo é ... kernel monolitico :-)

Ma forse kernel non modulare é forse anche meglio ...
[OT]

Il kernel Linux e` sempre monolitico, incorpora tutto quello che serve alla macchina,
i kernel Minix e Plan 9 sono microkernel, ogni cosa viene solo aggiunta quando serve.

http://www.osnews.com/story/15960/Intro ... o-MINIX-3/

Di un programma compilato con shared libraries file dice dynamically linked (uses shared libs),
di uno compilato con l'opzione -static dice statically linked.

Quindi un kernel che non carica moduli e` statico,
altrimenti e` un kernel che usa moduli, kernel modulare magari.

Re: GCC 3.3.6 vs GCC 4.2 - time()

Inviato: dom 13 set 2009, 15:35
da Calzo
Mario Vanoni ha scritto:Il kernel non usa glibc & co., e` autosufficiente.
Sì ok, ma quando il programma viene linkato le varie funzioni di sistema fino all'istruzione int 0x80 dovrebbero essere definite nelle glibc... quindi se ottimizzo quelle dovrei essere a posto.

...almeno se non ricordo male...
bye

Re: GCC 3.3.6 vs GCC 4.2 - time()

Inviato: dom 13 set 2009, 16:38
da Mario Vanoni
Calzo ha scritto:
Mario Vanoni ha scritto:Il kernel non usa glibc & co., e` autosufficiente.
Sì ok, ma quando il programma viene linkato le varie funzioni di sistema fino all'istruzione int 0x80 dovrebbero essere definite nelle glibc... quindi se ottimizzo quelle dovrei essere a posto.

...almeno se non ricordo male...
bye
Fai confusione tra kernel ed i programmi tuoi.
Il kernel non dipende da glibc, ha i sui strcpy ecc.,
e cambiano magari ad ogni nuova versione.
Un programma tuo:
- compilato con gcc-3.3.6 e glibc compilata con gcc-3.3.6
- compilato con gcc-4.2.4 e glibc compilata con gcc-3.3.6
- compilato con gcc-4.2.4 e glibc compilata con gcc-4.2.4
metti un caso estremo e molto improbabile
- compilato con gcc-3.3.6 e glibc compilata con gcc-4.2.4
i quattro programmi possono dare resultati inattesi.