|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 | |
|
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:
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);
}
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 Grazie in anticipo. |
|
|
|
|
|
|
#2 |
|
Senior Member
Iscritto dal: Nov 2005
Città: Texas
Messaggi: 1722
|
Nel main() hai scritto:
Codice:
struct quartiere *lista;
lista=NULL;
int i=0;
inshq(&lista);
__________________
In God we trust; all others bring data |
|
|
|
|
|
#3 | |
|
Senior Member
Iscritto dal: Nov 2005
Città: Texas
Messaggi: 1722
|
Quote:
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 |
|
|
|
|
|
|
#4 |
|
Senior Member
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;
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;
}
__________________
In God we trust; all others bring data |
|
|
|
|
|
#5 |
|
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; Codice:
p->act=NULL; 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 |
|
|
|
|
|
#6 | |
|
Senior Member
Iscritto dal: Nov 2005
Città: Texas
Messaggi: 1722
|
Quote:
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 |
|
|
|
|
|
|
#7 |
|
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! |
|
|
|
|
|
#8 | |
|
Senior Member
Iscritto dal: May 2001
Messaggi: 12966
|
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:
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. |
|
|
|
|
|
|
#9 | |
|
Member
Iscritto dal: Feb 2011
Messaggi: 46
|
Quote:
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 |
|
|
|
|
|
|
#10 |
|
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 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! |
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 18:34.












.








