Torna indietro   Hardware Upgrade Forum > Software > Programmazione

Peugeot Polygon Concept: ecco il futuro delle utilitarie
Peugeot Polygon Concept: ecco il futuro delle utilitarie
Polygon è la concept car di Peugeot che mostra il futuro delle soluzioni del segmento B: tra design compatti e innovativi affiancati da dimensioni compatte uno scherzo dalla manovrabilità incredibile per le manovre a bassa velocità
Reno16 Pro: il compatto di OPPO punta su fotocamera da 200MP e il nuovo Bubble! La recensione
Reno16 Pro: il compatto di OPPO punta su fotocamera da 200MP e il nuovo Bubble! La recensione
OPPO ha portato in Italia, dal 1° luglio 2026, Reno16 Pro: display AMOLED da 6,32 pollici a 144Hz, tripla fotocamera con sensore principale da 200 megapixel, chip Dimensity 8550 Super e batteria da 6000mAh, al prezzo di lancio di 899 euro. Lo abbiamo provato per due settimane insieme al nuovo accessorio Bubble, per capire se la formula compatta della serie regge ancora di fronte a un listino da 1099 euro
 Hisense 55U7SE: tuttofare e accessibile, il MiniLED per film, sport e gioco
Hisense 55U7SE: tuttofare e accessibile, il MiniLED per film, sport e gioco
MiniLED di fascia media con local dimming a 192 zone, 144 Hz nativi e audio firmato Devialet. La prova strumentale riscontra colori affidabili e gaming reattivo, per un prodotto molto accessibile e convincente. Ma la soundbar aggiuntiva è quasi d'obbligo
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 19-08-2018, 23:25   #1
vicko98
Junior Member
 
Iscritto dal: Aug 2018
Messaggi: 4
Su linux funziona, su Windows no [C]

Salve,

mi sto preparando per un esame universitario basato sul linguaggio C.
Ho svolto una traccia di qualche esame fa in cui veniva chiesto di creare una lista con una sottolista annidata, inserendo prima i dati nella lista principale in maniera ordinata, mentre nella sottolista è richiesto un inserimento in coda.

il testo è questo:
Quote:
Un servizio di assistenza clienti utilizza un archivio informatico in cui gli interventi di assistenza
vengono organizzati in funzione del nome del quartiere in cui si deve effettuare l'intervento. In
particolare, la struttura dati utilizzata include una lista che contiene le seguenti informazioni:

Nome Quartiere
Coda degli interventi

Dove il campo Nome Quartiere specifica il nome di uno dei quartieri in cui è divisa la città in cui
opera il servizio di assistenza.
La lista è realizzata con puntatori ed è ordinata per Nome di Quartiere.
Per ogni elemento della lista, oltre al campo Nome Quartiere, è memorizzata la coda degli
interventi. Tale coda contiene tutti gli interventi da eseguire in ciascun quartiere, memorizzati in
ordine temporale di arrivo. Ciascun elemento della coda degli interventi contiene i dati del
cliente che ha richiesto l’intervento di assistenza, e cioè:

Cognome
Nome
Via
Telefono
Tipo di Intervento Richiesto
Descrizione dell'intervento richiesto

La coda degli interventi è realizzata con puntatori.
Il tipo di intervento è codificato con un opportuno codice definito tramite enum
Codificare in Linguaggio C:

 le strutture dati utilizzate;
 una procedura di inserimento di un nuovo quartiere (non presente in archivio);
 una procedura di inserimento di una richiesta di intervento. Se il quartiere non esiste, viene
inserito in archivio;
 una procedura che indichi il numero di interventi per ciascun quartiere;
 una procedura che riceve in ingresso il nome di un quartiere e che in uscita fornisce tutti i dati
del primo intervento presente in coda per quel quartiere. Tale richiesta viene quindi eliminata
dalla coda;
 Il main che richiama opportunamente le procedure precedenti.

Durata della prova: 2 ore
il codice è questo:

Codice:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
enum tipo {inst,exe,test};
struct intervento
{
    char cognome[20];
    char nome[20];
    char via[30];
    char telefono[15];
    enum tipo t;
    char info[30];
    struct intervento *next;
};
struct quartiere
{
    char nomehq[20];
    struct intervento *act;
    struct quartiere *next;
};
void inshq(struct quartiere** list)
{
    struct quartiere *p,*g,*t=*list,*scorri=*list;
    int status=0;
    p=(struct quartiere*)malloc(sizeof(struct quartiere));
    p->next=NULL;
    //p->act=(struct intervento*)malloc(sizeof(struct intervento));
    //p->act->next=NULL;
    printf("Inserisci un nome di un quartiere: ");
    scanf("%s",p->nomehq);
    while(scorri!=NULL)
        {
            if(strcmp(p->nomehq,scorri->nomehq)==0)
                {
                    status=1;
                    printf("Quartiere giC  esistente! Inserire un altro nome \n");
                    return;
                }
            else status=0;
            scorri=scorri->next;
        }
        if(status==0)
            {
                if(*list==NULL)
                    {
                        *list=p;
                    }
                else
                    {
                        for(g=*list;g!=NULL&&strcmp(g->nomehq,p->nomehq)<0;t=g,g=g->next);
                        if(t==g)
                            {
                                p->next=*list;
                                *list=p;
                            }
                        else
                            {
                                t->next=p;
                                p->next=g;
                            }
                    }
            }
}

void inscoda(struct quartiere **list)
{
    char namehq[20];
    int status=0;
    struct quartiere *scorri=*list;
    printf("Inserire nome quartiere: ");
    scanf("%s",namehq);
    while(scorri!=NULL)
    {
        if(strcmp(scorri->nomehq,namehq)==0)
            {
                printf("Quartiere trovato \n");
               status=1;
               struct intervento *p;
               p=(struct intervento*)malloc(sizeof(struct intervento));
               p->next=NULL;
               printf("Inserisci Cognome: ");
               scanf("%s",p->cognome);
               printf("Inserisci Nome: ");
               scanf("%s",p->nome);
               printf("Inserisci Via: ");
               scanf("%s",p->via);
               printf("Inserisci Telefono: ");
               scanf("%s",p->telefono);
               printf("Inserisci Tipo intervento [0=install|1=Esecuzione|2=Test] : ");
               scanf("%d",&(p->t));
               while(getchar()!='\n');
               printf("Inserisci descrizione intervento: ");
               fgets(p->info,31,stdin);
               if(scorri->act==NULL)
                {
                    scorri->act=p;
                    return;
                }
               else
                {
                    struct intervento *scorri1=scorri->act;
                    //while(scorri1->next!=NULL)scorri1=scorri1->next;
                    scorri1->next=p;
                }
            }
        else status=0;
        scorri=scorri->next;
    }
    if(status==0)inshq(list);

}


void stampa(struct quartiere **list)
{
    struct quartiere *scorri=*list;
    while(scorri!=NULL)
        {
            printf("Nome quartiere: %s \n",scorri->nomehq);
            struct intervento *scorri1=(*list)->act;
            while(scorri1!=NULL)
                {
                    printf("Cognome:%s \n",scorri1->cognome);
                    scorri1=scorri1->next;
                }
            scorri=scorri->next;
        }
}
void cont(struct quartiere **list,char nhq[30])
{
    struct quartiere *scorri=*list;
    int i=0,stat=0;
    while(scorri!=NULL)
        {
            if(strcmp(nhq,scorri->nomehq)==0)
                {
                    struct intervento* scorri1=scorri->act;
                    while(scorri1!=NULL)
                        {
                            i++;
                            scorri1=scorri1->next;
                        }
                        printf("Numero interventi quartiere: %s \n Interventi n. %d",scorri->nomehq,i);
                        return;
                }
            scorri=scorri->next;
        }
        printf("non sono stati trovati quartieri con quel nome! \n");
}
void cerca(struct quartiere **list,char nhq[20])
{
    struct quartiere *scorri=*list;
    while(scorri!=NULL)
        {
            if(strcmp(scorri->nomehq,nhq)==0)
                {
                    struct intervento *p;
                    p=scorri->act;
                    scorri->act=scorri->act->next;
                    printf("Cognome del primo in coda: %s \n",p->cognome);
                    printf("Nome del primo in coda: %s \n",p->nome);
                    free(p);
                }
            scorri=scorri->next;
        }
}
int main()
{
    struct quartiere *lista;
    lista=NULL;
    int i=0;
    inshq(&lista);
    while(i<1){
    inscoda(&lista);
    i++;
    }
    cont(&lista,"tremestieri");
    cerca(&lista,"tremestieri");
    //stampa(&lista);
}
Il problema sorge sul sistema operativo utilizzato, se eseguito con il compilatore di linux(gcc) parte senza dare troppi problemi.
Mentre se eseguo lo stesso codice su windows, questo al termine dell'inserimento dei primi dati nella sottolista, fa return e termina il programma :

Codice:

Process returned -1073741819 (0xC0000005)   execution time : 21.037 s
Press any key to continue.

Ora, volendo..il docente utilizza esclusivamente linux, quindi ironicamente non sarebbe un problema , ma a me da fastidio lasciarlo così, vorrei capire quindi cosa fa infuriare windows con il proprio compilatore, qualcuno sa dirmi perchè?

Grazie in anticipo.
vicko98 è offline   Rispondi citando il messaggio o parte di esso
Old 20-08-2018, 15:45   #2
sottovento
Senior Member
 
L'Avatar di sottovento
 
Iscritto dal: Nov 2005
Città: Texas
Messaggi: 1722
Nel main() hai scritto:

Codice:
    struct quartiere *lista;
    lista=NULL;
    int i=0;
    inshq(&lista);
vai quindi a dereferenziare lista, che e' un puntatore a NULL. Il risultato non e' predicibile. Probabilmente il compilatore su linux cerca di dare senso a quell'operazione, mentre quello di Windows ti stoppa subito.
__________________
In God we trust; all others bring data
sottovento è offline   Rispondi citando il messaggio o parte di esso
Old 20-08-2018, 16:20   #3
sottovento
Senior Member
 
L'Avatar di sottovento
 
Iscritto dal: Nov 2005
Città: Texas
Messaggi: 1722
Quote:
Originariamente inviato da Bellaz89 Guarda i messaggi
Ma sei sicuro? A me questo sembra corretto, perche' alla fine nella funzione inshq non viene passato il puntatore ma la sua reference.
Ops, hai ragione. Sono stato troppo precipitoso.
Cmq se posso permettermi un consiglio: @vicko98, aggiungi sempre il controllo che la malloc() sia andata a buon fine. In caso contrario avrai dei crash senza spiegazione alcuna nel caso la malloc() fallisca
__________________
In God we trust; all others bring data
sottovento è offline   Rispondi citando il messaggio o parte di esso
Old 20-08-2018, 16:44   #4
sottovento
Senior Member
 
L'Avatar di sottovento
 
Iscritto dal: Nov 2005
Città: Texas
Messaggi: 1722
Ok, vediamo se prendo un'altra cantonata. @Bellaz89 correggimi se sbaglio ancora.

Nella
void inshq(struct quartiere** list)

si va a fare
Codice:
    p=(struct quartiere*)malloc(sizeof(struct quartiere));
    p->next=NULL;
Poi si scandisce la lista per inserire p nel caso il quartiere inserito non sia gia' presente.
Prima nota: nel caso il quartiere sia gia' presente ci sara' un memory leak!!!

La cosa interessante e' che il puntatore p->act non e' inizializzato, quindi punta a casaccio.
L'inserimento in inshq() andra' correttamente, mentre l'esecuzione fallira' quindi con un errore in inscoda():

Codice:
               if(scorri->act==NULL)
                {
                    scorri->act=p;
                    return;
                }
               else
                {
                    struct intervento *scorri1=scorri->act;
                    //while(scorri1->next!=NULL)scorri1=scorri1->next;
// SOTTOVENTO - qui
                    scorri1->next=p;
                }
Probabilmente vicko98 ha utilizzato Visual C++ per eseguire questo codice. In modalita' debug, Visual C++ inizializza i dangling pointer a 0xcdcdcdcd in modo che il debugger possa trovare il pattern e andare in crash immediatamente. Questo spiegherebbe la differenza di funzionamento sui due sistemi in oggetto.
__________________
In God we trust; all others bring data
sottovento è offline   Rispondi citando il messaggio o parte di esso
Old 21-08-2018, 19:39   #5
vicko98
Junior Member
 
Iscritto dal: Aug 2018
Messaggi: 4
Rieccomi,

Scusate se non ho risposto precedentemente, alla fine ho risolto il problema.


Codice:
//p->act=(struct intervento*)malloc(sizeof(struct intervento));
//p->act->next=NULL;
Era necessario definire che p->act fosse null, perchè la sottolista deve essere dichiarata vuota quando si crea un nuovo nodo, dunque ho risolto facendo :

Codice:
p->act=NULL;
(p->act->next=NULL effettivamente non aveva più senso)

Ho trovato la soluzione, ma non ho capito il motivo per cui linux riconosce comunque il puntatore, utilizzandone lo spazio offerto con la malloc..mentre windows riconosce qualche errore e termina li il programma, chissà...

Grazie per il vostro aiuto
vicko98 è offline   Rispondi citando il messaggio o parte di esso
Old 21-08-2018, 21:43   #6
sottovento
Senior Member
 
L'Avatar di sottovento
 
Iscritto dal: Nov 2005
Città: Texas
Messaggi: 1722
Quote:
Originariamente inviato da vicko98 Guarda i messaggi

Ho trovato la soluzione, ma non ho capito il motivo per cui linux riconosce comunque il puntatore, utilizzandone lo spazio offerto con la malloc..mentre windows riconosce qualche errore e termina li il programma, chissà...

Grazie per il vostro aiuto
Come ti dicevo, e' perche' non avendolo inizializzato avevi un dangling pointer.
In questo senso, Visual Studio e' piu' furbo: quando compili in modalita' debug, inizializza i dangling pointer a 0xcdcdcdcd e questo gli permette di trovare il problema subito e di visualizzartelo con un crash.
Il debugger di linux era decisamente meno furbo e per tua sfortuna il dangling pointer puntava ad una locazione valida. Quindi c'era l'errore anche su linux ma siccome puntava ad una locazione valida (anche se a caso) il software sembrava comunque funzionare
__________________
In God we trust; all others bring data
sottovento è offline   Rispondi citando il messaggio o parte di esso
Old 22-08-2018, 14:18   #7
fano
Senior Member
 
Iscritto dal: Nov 2005
Messaggi: 2095
+1 per Windows insomma.

Stresso anch'io questa cosa comunque: testa sempre i valori di ritorno delle funzioni! Su Linux malloc() in realtà non fallisce mai anche se chiedi più della memoria che il sistema realmente può darti (è un "bug" nascosto sotto lo strano nome di "optimistic memory allocation strategy"), altri OS fatti meglio tornano NULL in quei casi, quindi occhio!
__________________
Cosmos C# Open Source Managed Operating System
Cosmos Thread Ufficiale
Cosmos Official Site Vuoi collaborare allo sviluppo? Unisciti alla chat!
fano è offline   Rispondi citando il messaggio o parte di esso
Old 22-08-2018, 17:09   #8
WarDuck
Senior Member
 
L'Avatar di WarDuck
 
Iscritto dal: May 2001
Messaggi: 13012
Quote:
Originariamente inviato da fano Guarda i messaggi
+1 per Windows insomma.
Al massimo per il compilatore/linker .

Evidentemente VS in modalità debug sostituisce le routine di allocazione per l'heap con routine che inizializzano ad un valore noto.

Dovrebbe essere possibile fare la stessa cosa sotto Linux definendo la variabile d'ambiente: MALLOC_PERTURB_ ad un valore intero. Il suo negato viene usato per riempire la memoria allocata proprio per beccare situazioni strane.

http://man7.org/linux/man-pages/man3/mallopt.3.html

Quote:
Originariamente inviato da fano Guarda i messaggi
Stresso anch'io questa cosa comunque: testa sempre i valori di ritorno delle funzioni! Su Linux malloc() in realtà non fallisce mai anche se chiedi più della memoria che il sistema realmente può darti (è un "bug" nascosto sotto lo strano nome di "optimistic memory allocation strategy"), altri OS fatti meglio tornano NULL in quei casi, quindi occhio!
Premesso che bisogna controllare il valore di ritorno di malloc() a prescindere, la tua considerazione non c'entra niente con l'errore che ha riscontrato l'utente.

Nel suo caso infatti trattasi di memoria allocata correttamente ma non completamente inizializzata, in questo caso c'entra più che altro l'implementazione della malloc() della libreria C, che adotta un pool di memoria da riutilizzare per velocizzare l'allocazione. In questi casi è molto probabile che nella serie di malloc() free() malloc() ti venga riassegnata la stessa memoria.

Quando il sistema operativo (Linux) ti assegna una nuova pagina di memoria infatti questa viene sempre azzerata .

PS: sotto Linux con un compilatore abbastanza recente (gcc) se passi i flag "-Wall -Wextra" è molto probabile che ti dia dei warning sul fatto che utilizzi una variabile non inizializzata.

In ogni caso sempre sotto Linux è possibile utilizzare valgrind, che è una cosa che consiglio sempre quando ci sono problemi di questo tipo.

Cmq quello che bisogna stressare è compilare soprattutto con i warning abilitati: ho visto persone, anche esperte non farlo e per me è da bocciatura .

Ultima modifica di WarDuck : 22-08-2018 alle 17:12.
WarDuck è offline   Rispondi citando il messaggio o parte di esso
Old 22-08-2018, 19:35   #9
melko
Member
 
L'Avatar di melko
 
Iscritto dal: Feb 2011
Messaggi: 46
Quote:
Originariamente inviato da WarDuck Guarda i messaggi
Al massimo per il compilatore/linker .
PS: sotto Linux con un compilatore abbastanza recente (gcc) se passi i flag "-Wall -Wextra" è molto probabile che ti dia dei warning sul fatto che utilizzi una variabile non inizializzata.

In ogni caso sempre sotto Linux è possibile utilizzare valgrind, che è una cosa che consiglio sempre quando ci sono problemi di questo tipo.

Cmq quello che bisogna stressare è compilare soprattutto con i warning abilitati: ho visto persone, anche esperte non farlo e per me è da bocciatura .
concordo,
in questo caso però anche con -Wall -Wextra sia gcc che clang non danno warning sulla mancata inizializzazione,
una passata di valgrind invece lo evidenzia subito
melko è offline   Rispondi citando il messaggio o parte di esso
Old 23-08-2018, 12:55   #10
fano
Senior Member
 
Iscritto dal: Nov 2005
Messaggi: 2095
Anch'io un tempo abilitavo sempre -Wall -Wextra, ma ho notato un "difetto" (va beh oltre all'ovvio che "all" non abilita realmente tutto, ma ci sia "extra" pure) a volte segnala come warning complete sciocchezze e così ti perdi magari quelli "buoni" che - secondo me - in un linguaggio di programmazione serio sarebbero errori belli e buoni.

Ve ne racconto uno che è capitato ad un programmatore junior con monitor di recupero con pure "cluster" bruciati, dopo un merge di 2 branch CVS terrificante fatto alla "linux" (tutto a mano con 2 GVIM affiancati ) tutto compilava e poi andava allegramente in core!
Venivano generati tipo 150 warning quindi venivano tranquillamente ignorati
peccato che dopo circa 6 ore che riguardavamo il diff vediamo una cosa orrida: una sottrazione tra 2 stringhe! Uno dei "-" del diff si era magicamente spostato e "giaceva" su uno dei famosi cluster bruciati.

GCC lo warning lo aveva pure dato, che quella sottrazione tra stringhe non lo convinceva mica, ma poi aveva compilato lo stesso.

Io avevo anche provato a scegliere con cura quali -W abilitare, ma alla fine con ogni versione di GCC cambiano significato... questo è uno dei tanti enormi problemi del C.
__________________
Cosmos C# Open Source Managed Operating System
Cosmos Thread Ufficiale
Cosmos Official Site Vuoi collaborare allo sviluppo? Unisciti alla chat!
fano è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


Peugeot Polygon Concept: ecco il futuro delle utilitarie Peugeot Polygon Concept: ecco il futuro delle ut...
Reno16 Pro: il compatto di OPPO punta su fotocamera da 200MP e il nuovo Bubble! La recensione Reno16 Pro: il compatto di OPPO punta su fotocam...
 Hisense 55U7SE: tuttofare e accessibile, il MiniLED per film, sport e gioco Hisense 55U7SE: tuttofare e accessibile, il Min...
Kindle Scribe Colorsoft: riduce le cornici e diventa a colori, ma il prezzo è alto Kindle Scribe Colorsoft: riduce le cornici e div...
L'IA cambia tutte le regole della sicurezza tra vulnerabilità e sorveglianza. Intervista al CEO di Proofpoint L'IA cambia tutte le regole della sicurezza tra ...
SpaceX Starship: Ship 40 ha eseguito un ...
Redmi Note 17 a un passo dal debutto, ma...
Gli aumenti di prezzo del PS Plus potreb...
Almeno 64 GB di RAM per giocare? Il caso...
Gemini si integrerà con le auto e potrà ...
Addio a OxygenOS di OnePlus e alla Realm...
Intel conferma l'aumento dei prezzi su C...
In vendita Withings BodyFit, molto più d...
Inkterface: Steam Machine ospita un pann...
Stare seduti oltre 30 minuti di fila aum...
A Milano l'Italia ha firmato la sovranit...
Cos'è PeerTube, la piattaforma di...
In 12 articoli TOP c'è il meglio ...
La pirateria è l'unica tutela per...
Roomba Plus 516 Combo in offerta a 479€:...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 23:56.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Served by www3v