PDA

View Full Version : [Linux C] Qualcuno di voi mi aiuta?


DanieleC88
30-11-2004, 20:55
Sto creando una piccola libreria in C per facilitare il lavoro agli sviluppatori con le partizioni. Sarà disponibile solo su sistemi GNU/Unix, perchè si basa su GNU parted. Buona parte del codice è tratto e rielaborato da QtParted, il celebre software di partizionamento che cerca di essere simile a PartitionMagic.
Sto però trovando problemi nel crearla, perchè non sono molto esperto nell'uso di GNU libparted, non so come usare autoconf/automake e quindi uso un metodo di installazione abbastanza rozzo, e perchè ancora non me la cavo bene con la risoluzione degli errori e delle eccezioni in C. Se volete aiutarmi, contattatemi qui sul forum (in questa discussione, o in privato, se preferite) o scrivetemi una e-mail a «danielecocca at yahoo dot it».
Sono graditi anche consigli su come gestire il progetto su SourceForge.net (ho aperto il progetto, ma non so come fare l'upload dei files; qualcuno mi aveva consigliato di usare CVS, ma non so farlo: se sapete come usare CVS per questo proposito mandatemi istruzioni!!).

Se non volete aiutarmi nel progetto, almeno aiutatemi con questi errori! :(
Magari anche con un po' di istruzioni su come usare facilmente GDB, o una sua qualche intuitiva interfaccia per XFree86.
Usando il seguente codice, apro una pipe di un eseguibile per leggerne l'output, ma quando cerco di chiudere il relativo FILE * o di leggere una linea di output, ho solo un Segmentation Fault.

Il codice che effettua la chiamata:char * command, * line;
FILE * fp;

line = (char *) malloc(65 * 1024); /* 65 kb di memoria per l'output */
command = (char *) malloc(65 * 1024); /* 65 kb di memoria per la linea di comando */
sprintf(command, "%s %s -L %s", "/sbin/mkfs.ext3", "/home/daniele/virtual-disk", "VirtualDisk");
/* Apertura della pipe */
spec_cmdl_open(fp, command);
/* Lettura di una linea di output */
spec_cmdl_getl(fp, line);
/* Chiusura della pipe */
spec_cmdl_close(fp);
free(command);
free(line);

Il codice di spec_cmdl_....:bool spec_cmdl_open(FILE * pipe, const char * command)
{
char * redirected = (char *) malloc(65 * 1024);
bool redirect;

if (strstr(command, "2>&1") == NULL)
{
sprintf(redirected, "%s 2>&1", command);
redirect = true;
}

pipe = popen(redirect ? redirected : command, "r");
free(redirected);
return (pipe != NULL);
}

int spec_cmdl_close(FILE * pipe)
{
fflush(pipe);
return pclose(pipe);
}

char * spec_cmdl_getl(FILE * pipe, char * buffer)
{
char * line = (char *) malloc(65 * 1024);

fgets(line, sizeof(line), pipe);
buffer = line;
free(line);
return buffer;
/* return fgets(buffer, sizeof(buffer), pipe); */
}

Avviando GDB con "gdb libspec-test" e dando il comando "run" ottengo questa descrizione per il SIGSEGV:Program received signal SIGSEGV, Segmentation fault.
0x400fccd0 in _IO_link_in () from /lib/libc.so.6

Aspetto vostre risposte, magari posterò anche l'intero codice sorgente (un ammasso di bug, direi :)), se sarete interessati.

ilsensine
30-11-2004, 21:48
Il pipe viene allocato in spec_cmdl_open, ma il valore viene perso in quanto il puntatore FILE *fp è passato per copia e quindi non restituito al chiamante. Non è il modo per restituire valori da una funzione; hai un pò di confusione su cosa voglia dire passare un parametro a una funzione.

Prima di aprire un progetto su sf ti consiglio di fare un pò di pratica con il linguaggio. Chiedi pure se ti servono suggerimenti.

VICIUS
30-11-2004, 22:19
Originariamente inviato da DanieleC88
[...] non so come usare autoconf/automake e quindi uso un metodo di installazione abbastanza rozzo, [...]
in effetti all'inizio automake e autoconf non sono proprio il massimo. Se puoi prova con kdevelop riesci a gestire praticamente tutto tramite interfaccia. anche se forse è meglio che continui a fare tutto a manina. puo sembrare scocciante ma almeno impari ad usarlo per bene.

Originariamente inviato da DanieleC88
Sono graditi anche consigli su come gestire il progetto su SourceForge.net (ho aperto il progetto, ma non so come fare l'upload dei files; qualcuno mi aveva consigliato di usare CVS, ma non so farlo: se sapete come usare CVS per questo proposito mandatemi istruzioni!!).
cvs è piuttosto semplice da imparare. devi solo imparare due o tre comandi. prova ad installare il server in locale cosi puoi fare tutti gli esperimenti che ti pare. anche qui ci sono delle buone interfacce grafiche. cervisia è molto buono per esempio. da qualche parte devo ancora avere degli appunti/howto su come fare le cose piu banali. domani vedo se riesco a ritrovarlo.

Originariamente inviato da DanieleC88
Se non volete aiutarmi nel progetto, almeno aiutatemi con questi errori! :(
Magari anche con un po' di istruzioni su come usare facilmente GDB, o una sua qualche intuitiva interfaccia per XFree86.
anora una volta se usi kdevelop hai un interfaccia grafica integrata come visual studio. molto comoda. ne esistono pero anche altre di interfacie.

Originariamente inviato da DanieleC88
Usando il seguente codice, apro una pipe di un eseguibile per leggerne l'output, ma quando cerco di chiudere il relativo FILE * o di leggere una linea di output, ho solo un Segmentation Fault.
[...]
un piccolo appunto sul codice. non usare sprintf con un input che proviene da altri programmi/utenti tramite tastiera o pipe. molto meglio usare snprintf e prevenire buffer-overflow e segfault.

ciao ;)

VICIUS
01-12-2004, 12:50
Ho ritrovato i links. Quello sul cvs è un vero e proprio libro scaricabile liberamente: http://cvsbook.red-bean.com/. non ti serve sapere tutto. giusto il primo capitolo con i comandi principali per aggungere/rimuove file, fare commit e trovare le differenze. e un po del secondo per imparare ad amministrare un po il repository, fare l'import iniziale.

Se ti interessa apporfondire autoconf/automeke puoi guardare anche qui http://autotoolset.sourceforge.net/tutorial.html. tratta molte cose che non ti interessano ma c'è un capitolo fatto molto bene con degli esempi.

ciao ;)

DanieleC88
01-12-2004, 18:57
Grazie mille per i link, Vicius. Nel frattempo che mi scarico il libro e mi leggo quello che serve, mi vedo un po' "man cvs" e vedo cosa posso fare. :)

per ilsensine: hai ragione, era proprio lì l'errore (ora, almeno, il codice va senza segfaultare). In effetti, essendo totalmente autodidatta nel campo del computer, sono molto più pratico che teorico. Non sapevo nemmeno che i parametri restituiti fossero solo copie di valori locali (pensavo: "se passo il puntatore alla variabile, allora faccio riferimento alla sua precisa area di memoria"). BTW, ho risolto togliendo quel valore dai parametri e restituendolo con return.
Poi: il progetto su SF.net l'ho già aperto!! :) Forse lo chiudo, tanto se resta vuoto non mi serve a un granchè. Lo riaprirò quando sarà il momento.

DanieleC88
01-12-2004, 19:03
Originariamente inviato da VICIUS
in effetti all'inizio automake e autoconf non sono proprio il massimo. Se puoi prova con kdevelop riesci a gestire praticamente tutto tramite interfaccia.
non ho KDE, ed il mio 56k non mi permette di installarlo (è troppo pesante...)

Originariamente inviato da VICIUS
un piccolo appunto sul codice. non usare sprintf con un input che proviene da altri programmi/utenti tramite tastiera o pipe. molto meglio usare snprintf e prevenire buffer-overflow e segfault.

ciao ;)
in che modo può causare overflow?

VICIUS
01-12-2004, 20:16
fgets(line, sizeof(line), pipe);

line è un (char *) quindi tiene due byte. probabilmente volevi leggere
fino a 65k giusto ? visto che usi spesso questo numero perchè non usi
un #define? in questo modo se devi cambiarlo non devi rileggerti tutto
il codice.

sprintf(redirected, "%s 2>&1", command);

cosa succede se per un qualche motivo la funzione viene chiamata e
in command c'è una stringa lunga piu di 66555 caratteri ? che sprintf
sfora e ti va a scrivere in memoria. ma sopratutto attento che 65 * 1024
fa 66.5k e non 65. Riprova con 64.

ciao ;)

DanieleC88
02-12-2004, 13:06
oops, intendevo proprio usare 64, non 65 (mi ero confuso, perchè 64*1024=65536...)

poi io non uso il #define perchè sono casi isolati. intendevo adattare il malloc ad ogni specifico caso. ad esempio, qui ho scelto 64 kb perchè, da come ricordo di averlo letto tempo fa, BASH permette alla linea di comando di essere lunga al massimo 64 kb. (ma proprio perchè è un ricordo potrei sbagliarmi :))
l'output su stdout invece dici possa essere superiore a 64 kb? in effetti potrebbe essere vero, in fondo stdout non è altro che un file.
ciao!

DanieleC88
28-02-2005, 10:50
Scusatemi se riporto alla luce questa discussione ormai sepolta, ma è perché io sto ancora cercando collaboratori.
Un piccolo uppino pubblicitario, insomma. :)

Nel frattempo ho aggiornato sia la libreria che il progetto su SourceForge.net.
Ora la libreria usa gli Autotools e permette di fare molte più cose rispetto alla versione iniziale. Nella versione di sviluppo ho anche aggiunto alcune funzioni per ridimesionare PedGeometry e PedFileSystem, ma queste non sono ancora complete e disponibili nella release pubblica. Penso che farò l'upload su CVS appena posso.

Sito: http://libspec.sourceforge.net/