[MISTERO] C corruzione della memoria

Area di discussione libera.

Moderatore: Staff

Regole del forum
1) Rispettare le idee altrui.
2) Evitare le offese dirette.
3) Leggere attentamente le risposte ricevute
4) Scrivere i messaggi con il colore di default, evitare altri colori.
5) Scrivere in Italiano o in Inglese, se possibile grammaticalmente corretto, evitate stili di scrittura poco chiari, quindi nessuna abbreviazione tipo telegramma o scrittura stile SMS o CHAT.
6) Appena registrati è consigliato presentarsi nel forum dedicato.

La non osservanza delle regole porta a provvedimenti di vari tipo da parte dello staff, in particolare la non osservanza della regola 5 porta alla cancellazione del post e alla segnalazione dell'utente. In caso di recidività l'utente rischia il ban temporaneo.
Mario Vanoni
Iper Master
Iper Master
Messaggi: 3174
Iscritto il: lun 3 set 2007, 21:20
Nome Cognome: Mario Vanoni
Slackware: 12.2
Kernel: 3.0.4 statico
Desktop: fluxbox/seamonkey
Località: Cuasso al Monte (VA)

Messaggio da Mario Vanoni »

spina ha scritto:
Mario Vanoni ha scritto:

Codice: Seleziona tutto

....
       return(fprintf(stderr, "exiting\n"));
....
A mio avviso c'è un errore, non credi? Solo perchè in questo thread si è decantata più volte l'abilità di un programmatore e bla..bla..bla.

Cito dal man di fprintf:

Codice: Seleziona tutto

...
Return value
   Upon successful return, these functions return the number of  characters
printed
...
L'errore è sottile, ma tra l'altro in questo thread ci si è bisticciati per molto meno :)

Sono sicuro che avrai già capito a cosa mi riferisco, e sono sicuro anche che sarai d'accordo con me ;).

Spina
No, non capisco veramente, "exiting\n" sono 8 chars, echo $? dice 8.

Quanto scritto non si riferiva minimamente alla qualita` de[li] programmator[ei],
ma al linguaggio C, e di come gcc(1), splint(1) lo interpretano/controllano (sic!).

Mario Vanoni

Avatar utente
targzeta
Iper Master
Iper Master
Messaggi: 6563
Iscritto il: gio 3 nov 2005, 14:05
Nome Cognome: Emanuele Tomasi
Slackware: 64-current
Kernel: latest stable
Desktop: IceWM
Località: Carpignano Sal. (LE) <-> Pisa

Messaggio da targzeta »

Mario Vanoni ha scritto: No, non capisco veramente, "exiting\n" sono 8 chars, echo $? dice 8.

Quanto scritto non si riferiva minimamente alla qualita` de[li] programmator[ei],
ma al linguaggio C, e di come gcc(1), splint(1) lo interpretano/controllano (sic!).

Mario Vanoni
Si, hai ragione Mario, scusami, era una scemenza.
Mi riferivo al fatto che un programma dovrebbe "sempre" terminare con 0 in successo, è più o meno uno standard, e da buon programmatore mi sembrava un errore.

Ho interpretato male il tuo discorso, sorry again. Mi sembrava semplicemente una frecciatina verso lamarozzo, e la trovavo "inutile". Sai, non è facile capire cosa uno voglia dire se non ce l'hai veramente di fronte, a volte non basta neanche quello.

Spina
Linux Registered User #454438
Se pensi di essere troppo piccolo per fare la differenza, prova a dormire con una zanzara -- Dalai Lama
20/04/2013 - Io volevo Rodotà 

Avatar utente
lamarozzo
Linux 3.x
Linux 3.x
Messaggi: 732
Iscritto il: gio 14 lug 2005, 0:00
Desktop: xfce
Distribuzione: archlinux
Località: Roma

Messaggio da lamarozzo »

Scusa Mario non ho capito il post senza commenti (solo codice). Vuoi far vedere che si può andare oltre i limiti dichiarati nell'array senza che gcc e splint sollevino obiezioni?

Avatar utente
puzuma
Linux 2.x
Linux 2.x
Messaggi: 482
Iscritto il: mar 4 lug 2006, 17:14
Nome Cognome: Stefano Salvador
Slackware: current
Kernel: 2.6.32.2
Desktop: KDE 4.4.0
Località: Udine
Contatta:

Messaggio da puzuma »

estendendo un po' l'esempio di Mario:

Codice: Seleziona tutto

#include <stdio.h>

static double R[8];
static double S[8];

int main()
{
       R[0] = .1234;
       R[8] = 2.;
       R[9] = 999.999;

       printf("0 %f\n", R[0]);
       printf("1 %f\n", R[1]);
       printf("8 %f\n", R[8]);
       printf("9 %f\n", R[9]);
       printf("! %f\n", S[1]);
       return(fprintf(stderr, "exiting\n"));
}
da in output:

Codice: Seleziona tutto

0 0.123400
1 0.000000
8 2.000000
9 999.999000
! 999.999000
ovviamente come ci si aspetta S è stato modificato dalle operazioni in R, questo per molti (non per me, ma per un pacco di libri) è un comportamento da evitare, tra l'altro non so se lo standard prevede che gli array vengano creati contigui nello stack. Oltretutto così facendo mi pongo nella condizione che cambiando l'ordine di dichiarazione delle variabili cambia il risultato, è anche questo può limitare la leggibilità del codice.

Non sto dicendo che questo codice sia sbagliato o da evitare in assoluto, però è un comportamento che può dare dei problemi, possiamo discutere se la cosa debba essere segnalata dal compilatore o da un altro tool ma avere un programma automatico in grado di rilevare quella che può essere un'anomalia è molto utile.

Avatar utente
nuitari
Linux 3.x
Linux 3.x
Messaggi: 777
Iscritto il: dom 14 ott 2007, 12:51
Slackware: 12.0
Località: San Colombano al Lambro
Contatta:

Messaggio da nuitari »

Secondo me no invece. Ed anche secondo il C pare, in quanto quell'operatore (la parentesi quadra) è responsabile solo dell'alterazione dell'offset di un puntatore, e nient'altro.

Non è un caso se ogni libro decente sul C dice sempre "se volete gli array, createveli". E' linguaggio C, mica Basic. Ci crei driver e sistemi operativi, è quello l'utilizzo principale. Per cose + ad alto livello, ci sono linguaggi ad alto livello (già il C++ con il paradigma ad oggetti è + adatto).

Avatar utente
puzuma
Linux 2.x
Linux 2.x
Messaggi: 482
Iscritto il: mar 4 lug 2006, 17:14
Nome Cognome: Stefano Salvador
Slackware: current
Kernel: 2.6.32.2
Desktop: KDE 4.4.0
Località: Udine
Contatta:

Messaggio da puzuma »

nuitari ha scritto:Secondo me no invece. Ed anche secondo il C pare, in quanto quell'operatore (la parentesi quadra) è responsabile solo dell'alterazione dell'offset di un puntatore, e nient'altro.
sono daccordo, infatti non ho detto che è un comportamento sbagliato, tra l'altro ho scoperto di averlo usato anch'io in un mio programma qualche anno fa :oops: a volte però può essere causa di bug piuttosto fastidiosi, tali bug sono ovviamente causati dal programmatore, non dal c, avere però un tool (se preferite non chiamatelo compilatore) che rileva la cosa aiuta molte persone.

Francamente non sarei così arrogante da dire a queste persone di arrangarsi e di studiare meglio il c. del resto stiamo parlando solo di un warning che può essere in caso ignorato o sopresso.

Se i programmatori dell'intel hanno ritenuto opportuno inserilo un motivo ci sarà pure, direi che loro di cose a basso livello se ne intendono più di noi.

Avatar utente
puzuma
Linux 2.x
Linux 2.x
Messaggi: 482
Iscritto il: mar 4 lug 2006, 17:14
Nome Cognome: Stefano Salvador
Slackware: current
Kernel: 2.6.32.2
Desktop: KDE 4.4.0
Località: Udine
Contatta:

Messaggio da puzuma »

da un occhiata rapida a un paio di driver del kernel pare che quando una variabile viene dichiarata così:

Codice: Seleziona tutto

static double R[8]
non viene mai usato nessun indice oltre il 7, quanto si vogliono fare giochetti di altro tipo si preferisce:

Codice: Seleziona tutto

static double R[]
è solo una convenzione del resto ... a mio parere rende il codice un po' più chiaro.
Ultima modifica di puzuma il ven 14 dic 2007, 10:10, modificato 1 volta in totale.

Avatar utente
nuitari
Linux 3.x
Linux 3.x
Messaggi: 777
Iscritto il: dom 14 ott 2007, 12:51
Slackware: 12.0
Località: San Colombano al Lambro
Contatta:

Messaggio da nuitari »

Aridaje... :) Perchè devono inserire un controllo su una cosa non prevista dal linguaggio? :)

comunque non ho mai detto (io 8) ) nulla in merito ai programmatori in questione in questo topic. Personalmente, ho fatto errori ben peggiori, e non solo in C. Credo che si possa affermare che sbagliare sia un passo fondamentale del processo d'apprendimento, per cui nulla di male. Inoltre, se tutti sapessero tutto e facessero tutto giusto fin dall'inizio, a cosa diavolo servirebbe questo forum? ^_^

Secondo me i programmatori di Intel l'hanno aggiunto perchè Intel, come Microsoft, è una corporate, e fa quello che vuole. Quante cose ha fatto Microsoft che fanno cacare? Il fatto che lei le abbia fatte significa forse che son giuste? No.

Allo stesso modo, implementare controlli sulle [] allo scopo di usarle come array, è errato, MOLTO errato, perchè non sono il tipo di dato array. Per questo, io credo sia MEGLIO che gcc non supporti controlli di questo tipo, perchè così quando vuoi usare array come tipo dati, non essendo supportati dal linguaggio te li devi per forza programmare, sei obbligato.
Con il compilatore di intel invece puoi darla vinta alla pigrizia ed usare le [] per qualcosa che non sono in grado di fare.

Avatar utente
puzuma
Linux 2.x
Linux 2.x
Messaggi: 482
Iscritto il: mar 4 lug 2006, 17:14
Nome Cognome: Stefano Salvador
Slackware: current
Kernel: 2.6.32.2
Desktop: KDE 4.4.0
Località: Udine
Contatta:

Messaggio da puzuma »

nuitari ha scritto:Aridaje... :) Perchè devono inserire un controllo su una cosa non prevista dal linguaggio? :)
per lo stesso motivo per cui, come già rilevato in un altro post, hanno inserito almeno 12 estensioni al c non previste dallo standard: perchè l'uso e la convenzione hanno mostrato che spesso può essere una cosa utile.

comunque ribadisco: non mettetelo in gcc, ma perchè non in valgrid o altri tool che fanno decine di controlli "opinabili" ?

Avatar utente
nuitari
Linux 3.x
Linux 3.x
Messaggi: 777
Iscritto il: dom 14 ott 2007, 12:51
Slackware: 12.0
Località: San Colombano al Lambro
Contatta:

Messaggio da nuitari »

Perchè non 11? O magari nessuna? Che discorso è "visto che son 12 potevano farne 13"? E' come dire: ho tirato una martellata al muro e l'ho crepato, perchè non abbatterlo già che ci sono?

A sto punto se uno vuole può anche patcharsi GCC e aggiungere quel tipo di controllo e pure la pizza margerita se gli va. Per inciso esistono patch di terze parti che aggiungono sta cosa (il controllo, non la pizza margherita).

Il motivo per cui soft esterni non lo fanno è che è un controllo che va fatto in runtime, il codice deve aggiungerlo il compilatore in fase di compilazione, come accade per --fcheck-bounds.

Avatar utente
puzuma
Linux 2.x
Linux 2.x
Messaggi: 482
Iscritto il: mar 4 lug 2006, 17:14
Nome Cognome: Stefano Salvador
Slackware: current
Kernel: 2.6.32.2
Desktop: KDE 4.4.0
Località: Udine
Contatta:

Messaggio da puzuma »

mi sembrava che Mario avesse correttamante riportato la discussione su un piano esclusivamante tecnico.

il mio esempio voleva solo mostrare che l'uso dell'operatore [] senza alcune precauzioni possa portare a dei problemi e dei comportamenti imprevisti, infatti ho controllato e gcc non assicura di alocare la memoria in modo contiguo: nel mio esempio il valore di S[0] è indefinito e questo non è un bene.

Poi ho verificato molto velocemente che "normalmente" nei driver del kernel non si va mai oltre la lunghezza dell'array, e qui posso anche essere smentito.

Infine nessuno ha mai sentito parlare di "buffer overflow" ?

Simone_R
Linux 2.x
Linux 2.x
Messaggi: 218
Iscritto il: mar 12 apr 2005, 0:00
Contatta:

Messaggio da Simone_R »

puzuma ha scritto:mi sembrava che Mario avesse correttamante riportato la discussione su un piano esclusivamante tecnico.

il mio esempio voleva solo mostrare che l'uso dell'operatore [] senza alcune precauzioni possa portare a dei problemi e dei comportamenti imprevisti, infatti ho controllato e gcc non assicura di alocare la memoria in modo contiguo: nel mio esempio il valore di S[0] è indefinito e questo non è un bene.

Poi ho verificato molto velocemente che "normalmente" nei driver del kernel non si va mai oltre la lunghezza dell'array, e qui posso anche essere smentito.

Infine nessuno ha mai sentito parlare di "buffer overflow" ?
Attenzione ....

se usi

int a[100]
la memoria viene allocata in modo statico e contiguo prova a rimpiazzare 100 con 10000 e guarda la dimensione dell'eseguibile risultate.

Chiaramente se alla posizione 101 del vettore il compilatore ci mette lo spazio per la variabile b e tu ci scrivi sopra ... affari tuoi [il c non prevede nessun controllo sui vettori].

Se invece usi
int *a; cioè usi un vettore dinamico. al momento dell'allocazione il sistema fa quello che vuole quindi la contiguità può esserci come può non esserci e se sfori segmantation fault non è garantito al 100%.

Avatar utente
lamarozzo
Linux 3.x
Linux 3.x
Messaggi: 732
Iscritto il: gio 14 lug 2005, 0:00
Desktop: xfce
Distribuzione: archlinux
Località: Roma

Messaggio da lamarozzo »

vorrei sviluppare un po' l'esempio

Codice: Seleziona tutto

#include<stdio.h>

static double R[8];

int main()
{
        printf("%lf\n",R[8]);
        return 0;
}
L'output del codice è 0.00000

Ora ho fatto girare questo codice con Valgrind e non rileva nulla. Il fatto secondo me è preoccupante perchè lo standard prevede che gli array statici vengano inizializzati a zero. Soltanto che l'inizializzazione non dovrebbe riguardare anche l'elemento R[8] perchè non fa parte dell'array. Quindi sto leggendo una zona di memoria che in teoria neanche dovrebbe essere inizializzata e niente mi avverte dell'errore. Perchè?
Avrei trovato più aderente allo standard leggere in R[8] un valore casuale e poi Valgrind mi avrebbe dovuto segnalare che sto leggendo da una zona di memoria non inizializzata. Evidentemente non lo fa perchè il compilatore non sta inizializzando solo i primi 8 elementi ma anche oltre, cosa non prevista (ma forse neanche esclusa) dallo standard.

Che ne dite?

Avatar utente
puzuma
Linux 2.x
Linux 2.x
Messaggi: 482
Iscritto il: mar 4 lug 2006, 17:14
Nome Cognome: Stefano Salvador
Slackware: current
Kernel: 2.6.32.2
Desktop: KDE 4.4.0
Località: Udine
Contatta:

Messaggio da puzuma »

io indendevo che R ed S non è detto siano contigui, sulla mia piattaforma pare di si, altrove non si sa.

Avatar utente
puzuma
Linux 2.x
Linux 2.x
Messaggi: 482
Iscritto il: mar 4 lug 2006, 17:14
Nome Cognome: Stefano Salvador
Slackware: current
Kernel: 2.6.32.2
Desktop: KDE 4.4.0
Località: Udine
Contatta:

Messaggio da puzuma »

stai leggendo parti della memoria il cui contenuto è indefinito, probabilmente compilando con alcune opzioni di ottimizzazione leggerai altre cose.

Rispondi