Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Linea di comando per gcc

5 views
Skip to first unread message

guido84

unread,
Jun 2, 2017, 5:42:58 PM6/2/17
to
Su it.comp.lang.c mi e' stato detto che e' meglio non mettere
il "-lm" in questa linea di comando:
$: gcc -Wall -O3 log_e.c -lm -o log_e

Il sorgente log_e.c fatto apposta e' questo:
--------------
#include <stdio.h>
#include <math.h>

int main()
{
double enne;
scanf("%lf", &enne);
printf("\nlog(%lf) = %lf\n\n", enne, log(enne));

return 0;
}
-----------------

Ebbene, io sono un principiante, chi me l'ha detto ha esperienza
ma non di Linux (usa Windows NT) e m'ha suggerito di cambiare:
double enne; -> double enne = 0.0;

ma Ld continua a non trovare le librerie:
----------
/tmp/ccwk0tkr.o: nella funzione "main":
prova.c:(.text.startup+0x2d): riferimento non definito a "log"
collect2: error: ld returned 1 exit status
-----

Potreste darmi una dritta su questa questione grazie in anticipo?

--
Saluti,
Guido

enoquick

unread,
Jun 2, 2017, 9:36:01 PM6/2/17
to
enne e' usato solo per l'input,quindi non serve inizializzarlo.
Per il linker occorre dare -lm per includere la libreria matematica che
contiene log
Non vedo dove sta il problema.
Piuttosto se si vuole fare le cose per bene occorre porsi la domanda
'che succede se un utente immette un qualcosa che non sia convertibile
in double?'

guido84

unread,
Jun 3, 2017, 2:56:14 AM6/3/17
to
Il 3/6/2017 03:36:01 enoquick scrisse:
>Il 02/06/2017 16:42, guido84 ha scritto:

>> Su it.comp.lang.c mi e' stato detto che e' meglio non mettere
>> il "-lm" in questa linea di comando:

>> $: gcc -Wall -O3 log_e.c -lm -o log_e

>> Il sorgente log_e.c fatto apposta e' questo:
>> --------------
>> #include <stdio.h>
>> #include <math.h>
>>
>> int main()
>> {
>> double enne;
>> scanf("%lf", &enne);
>> printf("\nlog(%lf) = %lf\n\n", enne, log(enne));
>>
>> return 0;
>> }
>> -----------------
>>
>> Ebbene, io sono un principiante, chi me l'ha detto ha esperienza
>> ma non di Linux (usa Windows NT) e m'ha suggerito di cambiare:
>> double enne; -> double enne = 0.0;
>>
>> ma Ld continua a non trovare le librerie:
>> ----------
>> /tmp/ccwk0tkr.o: nella funzione "main":
>> prova.c:(.text.startup+0x2d): riferimento non definito a "log"
>> collect2: error: ld returned 1 exit status
>> -----
>>
>> Potreste darmi una dritta su questa questione grazie in anticipo?
>>

>enne e' usato solo per l'input, quindi non serve inizializzarlo.
>Per il linker occorre dare -lm per includere la libreria matematica che
>contiene log

Grazie della rispota, hai confermato quel che pensavo.

>Non vedo dove sta il problema.

Ho usato la linea di comando con "-lm", un certo "jak" mi ha detto
su it.comp.lang.c di NON usarla perche' potrebbe causare errori.
Copio e incollo:
-------------
Quasi tutti i compilatori, quando vedono utilizzare dati in
virgola mobile, includono una libreria matematica. Nella fattispecie, il
gcc ne utilizza una versione composta da built-in function che magari
non è la migliore ma sicuramente produce file eseguibili dalle
dimensioni più contenute. Potresti anche volerne utilizzare una ottenuta
da terze parti e non quella standard e siccome il parametro -lm utilizza
la 'fast link table' e cioè cerca nei percorsi che hai dichiarato una
libreria che inizia per 'lib' e finisce per quel che hai messo dopo la
'l' (in questo caso libm.a) ti troveresti, in questo caso errori del
linker per entry duplicate. Quindi no, l'opzione -lm non _deve_ esser
messa, eventualmente _può_.
Approfitterei anche per far notare che la portabilità dipende da come
scrivi il codice sorgente e, sicuramente, non dalle librerie con cui
linki il codice oggetto compilato. Anzi.
------------

>Piuttosto se si vuole fare le cose per bene occorre porsi la domanda
>'che succede se un utente immette un qualcosa che non sia convertibile
>in double?'

Si' ma quel codice l'avevo scritto (per jak) solo per vedere se
riuscivo a compilare senza usare "-lm". Comunque quelli della
libreria math.h sono bravissimi, perche' m'aspettavo un segfault,
invece ecco cosa mi dice:
$ echo vediamo | ./log_e

log(-0.000000) = nan

e questo con qualunque altra parola o lettera in input.
Grazie di nuovo e ciao

P.S. Ne approfitto: se volessi evitare di dover dare l'input con
"echo ... | ", ma darlo come si fa con $1 a bash, come dovrei
cambiare il sorgente?
Non e' mica facile trovarlo il modo, perche' ho provato con
sscanf() ma mi fa casini inenarrabili :-(


--
Saluti,
Guido

Alessandro Pellizzari

unread,
Jun 3, 2017, 3:39:46 AM6/3/17
to
On 03/06/17 07:56, guido84 wrote:

> P.S. Ne approfitto: se volessi evitare di dover dare l'input con
> "echo ... | ", ma darlo come si fa con $1 a bash, come dovrei
> cambiare il sorgente?
> Non e' mica facile trovarlo il modo, perche' ho provato con
> sscanf() ma mi fa casini inenarrabili :-(

Non sono sicuro di aver capito del tutto la domanda, perche` solitamente
e` la prima cosa che trovi nei manuali di C, ma credo ti basti leggere
argv[1] (dopo aver controllato che argc sia >2)

Qualcosa tipo (il mio C e` un po' arrugginito):

int main(int argc, char** argv) {
double enne;
if (argc>2) {
sscanf(argv[1], "%lf", enne);
printf...
}
}

Bye.

guido84

unread,
Jun 3, 2017, 4:38:55 AM6/3/17
to
Il 3/6/2017 09:39:43 Alessandro Pellizzari scrisse:
>On 03/06/17 07:56, guido84 wrote:

>> P.S. Ne approfitto: se volessi evitare di dover dare l'input con
>> "echo ... | ", ma darlo come si fa con $1 a bash, come dovrei
>> cambiare il sorgente?
>> Non e' mica facile trovarlo il modo, perche' ho provato con
>> sscanf() ma mi fa casini inenarrabili :-(

>Non sono sicuro di aver capito del tutto la domanda, perche` solitamente
>e` la prima cosa che trovi nei manuali di C,

Si' ma il fattaccio e' che io il C non l'ho mai studiato come
teoria, lo imparo man mano facendo programmi.

>ma credo ti basti leggere
>argv[1] (dopo aver controllato che argc sia >2)

Sembra che argc corrisponda a $2, e' andato tutto benissimo, ma mi
tocca dare il comando: "./prova 10 qualsiasi_cosa".

>Qualcosa tipo (il mio C e` un po' arrugginito):

>int main(int argc, char** argv) {
> double enne;
> if (argc>2) {
> sscanf(argv[1], "%lf", enne);
> printf...
> }
>}

Cosi', per evitare il $2 = terzo argomento della riga, ho tolto
la condizione e va perfettamente.
-------------
#include <stdio.h>
#include <math.h>

int main(int pippo, char** argv)
{
double enne;
sscanf(argv[1], "%lf", &enne);
printf("\nlog(%lf) = %lf\n\n", enne, log(enne));

return 0;
}
------------

Grazie!! Di dover mettere "int" e ancor peggio "char**" dentro la
tomda di main non ci sarei mai arrivato! e che cavoli l'input e'
in double! :-(
Be' adesso posso passare alla doc nei sacri testi, cosi' almeno
-avendo un esempio concreto- ci riusciro' a capire cosa diavolo
dicono per sscanf().

Ciao e grazie di nuovo

--
Saluti,
Guido

Giuseppe Della Bianca

unread,
Jun 3, 2017, 8:52:20 AM6/3/17
to
guido84 wrote:

]zac[
> Cosi', per evitare il $2 = terzo argomento della riga, ho tolto
> la condizione e va perfettamente.
]zac[

E quello che hai ottenuto e di avere un programma pronto per un accesso
fuori dalla memoria, hai presente i bug che usano i cracker per bucare i
sistemi degli altri.

Il vettore argv e' popolato in base hai parametri passati, il resto contiene
dati non sicuri (dipende al contenuto della memoria in quel momento).

Prima di leggere argv bisogna controllare leggere argc per sapere il numero
di item presenti in argv .

Nel tuo caso il test avrebbe dovuto essere argc == 2 o argc >= 2.




E' vero che stai facendo un programma di prova, ma tieni conto che se non si
tiene conto continuamente dei problemi di sicurezza e solidita', dopo che il
programma e' cresciuto o si e' assunto uno stile di programmazione, e' molto
difficile correggerlo e correggersi.




P.S. Se non hai motivazione particolari per usare solo il C, e' saggio
imparare il C++.
Personalmente trovo uno spreco di tempo inutile doversi sempre preoccupare
di puntatori, dimensione dei vettori, di stringhe, di strutture complesse,
sfugge sempre qualcosa.

Alessandro Pellizzari

unread,
Jun 3, 2017, 9:38:23 AM6/3/17
to
On 03/06/17 09:38, guido84 wrote:

> Si' ma il fattaccio e' che io il C non l'ho mai studiato come
> teoria, lo imparo man mano facendo programmi.

"Il Linguaggio C" di Kernighan e Ritchie sono 150 pagine, se non ricordo
male, e contiene praticamente tutta la base del linguaggio (librerie
escluse, per intenderci)


>> ma credo ti basti leggere
>> argv[1] (dopo aver controllato che argc sia >2)
>
> Sembra che argc corrisponda a $2, e' andato tutto benissimo, ma mi
> tocca dare il comando: "./prova 10 qualsiasi_cosa".

No.

argc e` il numero di parametri sulla command line

argv e` un array di stringhe, che in C si puo` rappresentare come un
puntatore a una lista di puntatori (da cui il doppio *)

Se scrivi "./prova 10 qualsiasi_cosa"

argc = 3
argv = ["./prova", "10", "qualsiasi_cosa"]

argv[0] e` sempre il comando che hai dato, quindi il primo parametro e`
argv[1] e via via i successivi.

Se accedi a argv[3], in questo caso, stai puntando a un'area di memoria
non inizializzata, quindi ti rendi vulnerabile ad attacchi di code
injection.

Bye.


guido84

unread,
Jun 3, 2017, 9:40:37 AM6/3/17
to
Il 3/6/2017 14:51:49 Giuseppe Della Bianca scrisse:
>guido84 wrote:

>]zac[
>> Cosi', per evitare il $2 = terzo argomento della riga, ho tolto
>> la condizione e va perfettamente.
>]zac[

>E quello che hai ottenuto e di avere un programma pronto per un accesso
>fuori dalla memoria, hai presente i bug che usano i cracker per bucare i
>sistemi degli altri.

L'ho sentito dire, senza pero' capirlo. OK.

>Il vettore argv e' popolato in base hai parametri passati, il resto contiene
>dati non sicuri (dipende al contenuto della memoria in quel momento).

Capito.

>Prima di leggere argv bisogna controllare leggere argc per sapere il numero
>di item presenti in argv.

Capito.

>Nel tuo caso il test avrebbe dovuto essere argc == 2 o argc >= 2.

Perfetto, l'ho rifatto con argc == 2, non c'e' neppur bisogno di
dargli l'else, se metto $2 termina senza far nulla, con solo $1 da'
istantaneamente il logaritmo.
Lo testo con:
$ ./prova $(echo "e(2.77)" | bc -l)
e mi restituisce:
log(15.958634) = 2.770000

--------------
int main(int argc, char** argv)
{
double enne;
if (argc==2)
{
sscanf(argv[1], "%lf", &enne);
printf("\nlog(%lf) = %lf\n\n", enne, log(enne));
}
return 0;
}
------------

>E' vero che stai facendo un programma di prova, ma tieni conto che se non si
>tiene conto continuamente dei problemi di sicurezza e solidita', dopo che il
>programma e' cresciuto o si e' assunto uno stile di programmazione, e' molto
>difficile correggerlo e correggersi.

Si', questo dovro' tenerlo presente.

>P.S. Se non hai motivazione particolari per usare solo il C, e' saggio
>imparare il C++.
>Personalmente trovo uno spreco di tempo inutile doversi sempre preoccupare
>di puntatori, dimensione dei vettori, di stringhe, di strutture complesse,
>sfugge sempre qualcosa.

Sentimentalmente mi piaceva il C puro (come il kernel), ma
provero' il c++. E poi soprattutto pensavo fosse piu' difficile
invece da questo che dici sembra piu' facile o almeno piu' veloce
e meno impegnativo.

Ciao e grazie del reply!!

--
Saluti,
Guido

guido84

unread,
Jun 3, 2017, 10:13:45 AM6/3/17
to
Il 3/6/2017 15:38:20 Alessandro Pellizzari scrisse:
>On 03/06/17 09:38, guido84 wrote:

>> Si' ma il fattaccio e' che io il C non l'ho mai studiato come
>> teoria, lo imparo man mano facendo programmi.

>"Il Linguaggio C" di Kernighan e Ritchie sono 150 pagine, se non ricordo
>male, e contiene praticamente tutta la base del linguaggio (librerie
>escluse, per intenderci)

Ce l'avevo (e' la Bibbia, no?), l'ho prestato, non l'ho piu' rivisto
ne' piu' lo rivedro' ,-) me lo dovro' ricompare, ANSI C era il mio.

>>> ma credo ti basti leggere
>>> argv[1] (dopo aver controllato che argc sia >2)
>>
>> Sembra che argc corrisponda a $2, e' andato tutto benissimo, ma mi
>> tocca dare il comando: "./prova 10 qualsiasi_cosa".

>No.

>argc e` il numero di parametri sulla command line

Ah ecco.. Ok.

>argv e` un array di stringhe, che in C si puo` rappresentare come un
>puntatore a una lista di puntatori (da cui il doppio *)

Gia', il tuo char-stella-stella.
Insomma se non capisco male:
- int argc e' perche' main riceve ovviamente un intero (# dei par.)
- mentre il "numero" enne, di cui fare il logaritmo, lo riceve come
srtinga di caratteri ascii da tradurre poi in numero double.

>Se scrivi "./prova 10 qualsiasi_cosa"

>argc = 3
>argv = ["./prova", "10", "qualsiasi_cosa"]

>argv[0] e` sempre il comando che hai dato, quindi il primo parametro e`
>argv[1] e via via i successivi.

Capito mersi'

>Se accedi a argv[3], in questo caso, stai puntando a un'area di memoria
>non inizializzata, quindi ti rendi vulnerabile ad attacchi di code
>injection.

Si', comincio a capire come funziona, me l'aveva appena accennato
anche Giuseppe D.B.

Grazie delle info e ciao!

--
Saluti,
Guido

enoquick

unread,
Jun 3, 2017, 10:07:07 PM6/3/17
to
Se fosse come dice lui non occorrerebbe includere libm quindi tira un po
tu le conclusioni.
Appunto: per default gcc fa il link dinamico quindi usa libm.so o simile
non libm.a
Per usare il link statico occorre l'opzione -static

>> Piuttosto se si vuole fare le cose per bene occorre porsi la domanda
>> 'che succede se un utente immette un qualcosa che non sia convertibile
>> in double?'
>
> Si' ma quel codice l'avevo scritto (per jak) solo per vedere se
> riuscivo a compilare senza usare "-lm". Comunque quelli della
> libreria math.h sono bravissimi, perche' m'aspettavo un segfault,
> invece ecco cosa mi dice:
> $ echo vediamo | ./log_e
>
> log(-0.000000) = nan
>
> e questo con qualunque altra parola o lettera in input.
> Grazie di nuovo e ciao
>
Pura fortuna,se enne non e' inizializzato e l'utente immette un valore
non valido il contenuto di enne e' spazzatura.

scanf ritorna un int per sapere quello che ha letto
(http://www.cplusplus.com/reference/cstdio/scanf/)


> P.S. Ne approfitto: se volessi evitare di dover dare l'input con
> "echo ... | ", ma darlo come si fa con $1 a bash, come dovrei
> cambiare il sorgente?
> Non e' mica facile trovarlo il modo, perche' ho provato con
> sscanf() ma mi fa casini inenarrabili :-(
>
>

i valori di input li puoi leggere in 3 modi (lascio stare altri modi piu
complessi come ipc,socket,shared memory,ecc..)
da file (anche stdin e' un file)
da argomenti (argc/argv)
da ambiente (env)
Puoi decidere tu come devi agire


guido84

unread,
Jun 4, 2017, 4:15:35 AM6/4/17
to
Il 4/6/2017 04:07:05 enoquick scrisse:
>Il 03/06/2017 01:56, guido84 ha scritto:

>Se fosse come dice lui non occorrerebbe includere libm quindi tira un po
>tu le conclusioni.

Si' ormai l'avevo gia' capito e gliel'ho detto che parliamo di
due programmi distinti: lui parla di gcc.exe e che inoltre il C
non c'entra.

>Appunto: per default gcc fa il link dinamico quindi usa libm.so o simile
>non libm.a
>Per usare il link statico occorre l'opzione -static

Capito. Ho provato con -static e infatti mi vengono file giganti.

>>> Piuttosto se si vuole fare le cose per bene occorre porsi la domanda
>>> 'che succede se un utente immette un qualcosa che non sia convertibile
>>> in double?'

>> Si' ma quel codice l'avevo scritto (per jak) solo per vedere se
>> riuscivo a compilare senza usare "-lm". Comunque quelli della
>> libreria math.h sono bravissimi, perche' m'aspettavo un segfault,
>> invece ecco cosa mi dice:
>> $ echo vediamo | ./log_e

>> log(-0.000000) = nan

>> e questo con qualunque altra parola o lettera in input.
>> Grazie di nuovo e ciao

>Pura fortuna, se enne non e' inizializzato e l'utente immette un valore
>non valido il contenuto di enne e' spazzatura.
>scanf ritorna un int per sapere quello che ha letto
>(http://www.cplusplus.com/reference/cstdio/scanf/)

OK, grazie e poi me lo leggo.

>> P.S. Ne approfitto: se volessi evitare di dover dare l'input con
>> "echo ... | ", ma darlo come si fa con $1 a bash, come dovrei
>> cambiare il sorgente?
>> Non e' mica facile trovarlo il modo, perche' ho provato con
>> sscanf() ma mi fa casini inenarrabili :-(

>i valori di input li puoi leggere in 3 modi (lascio stare altri modi piu
>complessi come ipc,socket,shared memory,ecc..)
>da file (anche stdin e' un file)

Si' su Linux ne so abbastanza OK.

>da argomenti (argc/argv)

Si' ormai ce l'ho chiaro (m'hanno gia' risposto anche altri).

>da ambiente (env)

Ok.

>Puoi decidere tu come devi agire

Si' grazie per tutte le info e ciao!

--
Saluti,
Guido

Giuseppe Della Bianca

unread,
Jun 4, 2017, 6:20:41 AM6/4/17
to
guido84 wrote:

]zac[
> L'ho sentito dire, senza pero' capirlo. OK.

Smashing The Stack For Fun And Profit

http://insecure.org/stf/smashstack.html

]zac[
> Sentimentalmente mi piaceva il C puro (come il kernel), ma
]zac[

Se stai iniziando, continua con quello che ti appassiona di piu.

La scelta del c puro nel kernel linux credo che sia una questione di
facilita' di debug.

Ma niente e' gratis.
(Personalmente la scelta la ritengo non giusta, devono scrivere chilometri
di codice in piu, con parecchi problemi in più).

> provero' il c++. E poi soprattutto pensavo fosse piu' difficile
> invece da questo che dici sembra piu' facile o almeno piu' veloce
> e meno impegnativo.

Dal lato della gestione della memoria si, e il compilatore del c++ e' molto
più preciso/rigido di quello del c .
Il c e' troppo permissivo, e' troppo facile scrivere programmi poco solidi.

Potresti scrivere in c puro usando il compilatore del c++ (ti basta usare
file xyz.cc invece che xyz.c ).

>
> Ciao e grazie del reply!!
>

:)
0 new messages