View Full Version : Stranezze del C
Andrea16v
17-09-2007, 22:13
Ho un segmentation fault che mi blocca inesorabilmente un programma che sto facendo, dopo averle provate un po' tutte, senza esito, ho fatto delle prove scrivendo questo programmino banale....
#include <stdio.h>
int main ()
{
char *parola;
printf("Inserisci una parola.\n");
scanf("%s", parola);
printf("La parola immessa e': %s", parola);
return 0;
}
Anche questo compila correttamente, ma mi genera un bel segmentation fault senza stampare niente, è il mio gcc che da' i numeri oppure qualcosa di sbagliato?
ilsensine
17-09-2007, 22:18
char parola[128];
Ovviamente sei a rischio di buffer overflow.
Andrea16v
17-09-2007, 22:43
char parola[128];
Ovviamente sei a rischio di buffer overflow.
Ma è normale che non funzioni il programma come lo avevo scritto? Penso di aver fatto centinaia di letture in quel modo e mai un problema.
Tra l'altro se aggiungo una dichiarazione di una variabile di tipo char, che non uso, il programma funziona correttamente, non riesco a capire perchè..
#include <stdio.h>
int main ()
{
char c;
char *parola;
printf("Inserisci una parola.\n");
scanf("%s", parola);
printf("La parola immessa e': %s", parola);
return 0;
}
:mbe:
ilsensine
17-09-2007, 23:20
Ma è normale che non funzioni il programma come lo avevo scritto?
Sì hai passato a scanf un puntatore non inizializzato
Tra l'altro se aggiungo una dichiarazione di una variabile di tipo char, che non uso, il programma funziona correttamente
per puro caso. Hai scritto comunque su una zona di memoria a caso.
Metti ad es.
char c;
char *parola = NULL;
e vedrai che il caro segfault ritorna.
Ziosilvio
18-09-2007, 10:20
Stranezze?
A me sembra "solo" mancata comprensione del funzionamento dei puntatori...
#include <stdio.h>
int main ()
{
char *parola;
A questo punto del programma, la variabile parola non è inizializzata, e contiene un valore a caso, puntando così a una zona di memoria totalmente arbitraria.
Adopera la funzione malloc per dedicare una regione di memoria cui far puntare la variabile parola.
printf("Inserisci una parola.\n");
scanf("%s", parola);
Usare scanf per leggere una stringa lunga non si sa quanto, è una prassi sconsigliata in qualunque manuale. (Senza contare, ovviamente, il fatto che stai cercando di scrivere in una zona a caso.)
Il mio consiglio è di usare fgets invece di scanf, tanto devi leggere stringhe e non valori numerici.
printf("La parola immessa e': %s", parola);
return 0;
}
Questo, invece, potrebbe funzionare... se il resto fosse corretto...
Ah: ovviamente, prima di terminare il programma, devi ricordarti di liberare la memoria allocata per la variabile parola, adoperando la funzione free.
nico88desmo
18-09-2007, 11:48
#include <stdio.h>
int main ()
{
char *parola;
printf("Inserisci una parola.\n");
scanf("%s", parola);
printf("La parola immessa e': %s", parola);
return 0;
}
Così dovrebbe funzionare
#include <stdio.h>
#include <malloc.h>
#define DIM_STR 50
int main {
char *parola;
parola = (char *) malloc (sizeof(char)*DIM_STR);
printf("Inserisci una parola.\n");
scanf("%s", parola);
printf("La parola immessa e': %s", parola);
return 0;
}
trallallero
18-09-2007, 12:17
Così dovrebbe funzionare
#include <stdio.h>
#include <malloc.h>
#define DIM_STR 64 //50
int main {
char *parola;
parola = (char *) malloc (sizeof(char)*DIM_STR);
printf("Inserisci una parola.\n");
scanf("%s", parola);
printf("La parola immessa e': %s", parola);
return 0;
}
se e´ fisso almeno allochiamo per potenze di 2 ;)
Andrea16v
18-09-2007, 12:36
Ho afferrato.. :D
Domanda: allocare dinamicamente n caratteri con la malloc o dichiarare direttamente un array di n posizioni è la stessa cosa ai fini pratici?
Es:
#define DIM_STR 32
char *parola;
parola = (char *) malloc (sizeof(char)*DIM_STR);
parola = bla bla...
free(parola);
è uguale al seguente o ci sono differenze di qualche tipo?
#define DIM_STR 32
char parola[DIM_STR]
parola = bla bla...
trallallero
18-09-2007, 12:38
Ho afferrato.. :D
Domanda: allocare dinamicamente n caratteri con la malloc o dichiarare direttamente un array di n posizioni è la stessa cosa ai fini pratici?
Es:
#define DIM_STR 32
char *parola;
parola = (char *) malloc (sizeof(char)*DIM_STR);
parola = bla bla...
free(parola);
è uguale al seguente o ci sono differenze di qualche tipo?
#define DIM_STR 32
char parola[DIM_STR]
parola = bla bla...
a parte discorso RAM , se sai la grandezza e´ piu´ furbo il secondo metodo. Allocazione dinamica serve proprio perche´ potresti non conoscere la dimensione ;)
Ziosilvio
18-09-2007, 12:49
allocare dinamicamente n caratteri con la malloc o dichiarare direttamente un array di n posizioni è la stessa cosa ai fini pratici?
Naturalmente no: un array statico quello è e quello rimane, mentre un array dinamico può anche essere ridimensionato con la funzione realloc.
Andrea16v
18-09-2007, 13:38
Naturalmente no: un array statico quello è e quello rimane, mentre un array dinamico può anche essere ridimensionato con la funzione realloc.
Ovviamente, quindi nel caso in cui non abbia bisogno di ridimensionare sempre meglio usare un "array statico".
Volendo usare fgets, come consigliato, il comando sarebbe una cosa del tipo:
fgets(parola, DIM_STR, stdin) ?
Se volessi controllare che la parola inserita contenga solo caratteri alfabetici (e non cifre, spazi o simboli vari), dovrei a posteriori scandire l'array char per char oppure ci sono dei parametri con cui poter direttamente chiamare fgets() ?
Ziosilvio
18-09-2007, 14:39
Volendo usare fgets, come consigliato, il comando sarebbe una cosa del tipo:
fgets(parola, DIM_STR, stdin) ?
Sì, perché fgets(str,len,stream) legge al più len-1 caratteri, e rimane sempre lo spazio per il terminatore.
Se volessi controllare che la parola inserita contenga solo caratteri alfabetici (e non cifre, spazi o simboli vari), dovrei a posteriori scandire l'array char per char oppure ci sono dei parametri con cui poter direttamente chiamare fgets() ?
Purtroppo l'unica è passare "al setaccio" la stringa letta con qualcuna delle funzioni definite in ctype.h o con una funzione creata per l'occasione.
nico88desmo
18-09-2007, 19:11
nel caso la grandezza della stringa la chiedi all'utente...potresti usare una cosa di questo tipo:
#ifndef DIM
#define DIM variabile_integer
char str[variabile_integer]
#endif
In pratica dici delle direttive al pre-processore
Comunque sia non è una buona cosa da fare. E' più che altro per imparare il linguaggio ;)
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.