PDA

View Full Version : [C] Problema allocazione memoria dinamica


Spe!
15-01-2013, 08:58
Buongiorno a tutti,
mi sono appena iscritto al forum per sapere da voi qualcosa in più riguardo ad un problema di esecuzione di un programma C.

Il sorgente del programma in questione è il seguente


//
// PROGRAMMA DI TIMING COUNTDOWN
// Il programma riceve da linea di comando n-argomenti (interi) in secondi.
//
// Il programma fa il refresh dello schermo costante.
// Visualizza nella prima riga il timer totale crescente e decrescente (somma di tutti i timing)
// Nella seconda riga scorrono, uno dopo l'altro, gli altri timer, con visualizzazione crescente e descrescente.
//
// Il programma, inoltre, può acquisire attraverso il flag '-f' un file che contiene i timers, separati da un carattere spaziatore. (da sviluppare)
//


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>


// FUNCTIONS PROTOTIPES
void print_error();
long int * timers_generate(const char * string_matrix[], int matrix_dim);


int main(int argc, const char * argv[])
{
// VARIABLE
long int *timers, total, total_in, current, current_in;
int i;
total = total_in = current = current_in = i = 0;
timers = NULL;

// INIZIALIZE SCREEN
system("clear");


// BODY SOURCE
//
// Checks numbers of argv:
// - no timer: views manual
// - > 1 timers: views countdown total and countdown current

switch (argc) {
case 1: // no args
print_error();
break;

default: // args > 1
timers = timers_generate(&argv[1], argc - 1);

if (timers != NULL) {

// Calcolo tempo totale
for (i = 1; i < timers[0]; i++)
total = total + timers[i];

// Visualizzo i timers
i = 1;
current = timers[i];
current_in = 0;

while (total_in < total) { // contatore totale

if (current_in == current && i < timers[0]) { // contatore parziale
i++;
current = timers[i];
current_in = 0;
}

printf("\t TIMER\n");
printf(" Total\t\t Current\n");
printf(" %02ld:%02ld\t\t %02ld:%02ld\n", total_in/60, total_in % 60, current_in/60, current_in % 60);
printf("-%02ld:%02ld\t\t -%02ld:%02ld\n", (total-total_in)/60, (total-total_in) % 60, (current-current_in)/60, (current-current_in) % 60);

if (i < timers[0]-1) {
printf(" Next %02ld:%02ld\n", timers[i+1]/60, timers[i+1] % 60);
}

sleep(1);
total_in++;
current_in++;

system("clear");

}

printf("Time's up!\n\n");

} else
print_error();
break;
}

}



// FUNZIONE DI GENERAZIONE DELL'ARRAY CON I TIMERS
//
// Input: puntatore a matrice di stringhe con dimensione
// Output: NULL se nessuna stringa è valida, puntatore se almeno 1 è valido (il primo valore del vettore corrisponde alla dimensione del vettore)
long int * timers_generate(const char *string_matrix[], int matrix_dim){

// Variabili
int i, j, is_correct, n_correct; i = j = 0; is_correct = 1; n_correct = -1;
long int *work, *timer_array;
work = timer_array = NULL;


// Alloco massima memoria (pensando che tutti i valori siano validi)
work = (long*)malloc(matrix_dim * sizeof(long));

if (work != NULL) { // allocazione corretta
// inizializzo array
for (i=0; i < matrix_dim; i++, work[i] = 0);

// elaboro
for (i = 0; i < matrix_dim; i++) {

is_correct = 1;
for (j = 0; j < strlen(string_matrix[i]) && is_correct; j++) { // 'strlen' viene sicuramente eseguita dato che la stringa non è nulla
if (isdigit(string_matrix[i][j]) == 0)
is_correct = 0;
}

if (is_correct) { // verifico se la stringa è valida
n_correct++; // conto da 0 per comodità del vettore

work[n_correct]=atol(string_matrix[i]);
}
}

if (n_correct >= 0) { // valuto il return e ottimizzo l'array creato

timer_array = (long*) malloc((n_correct+1+1) * sizeof(long));
// pongo in testa al vettore il numero di elementi presenti
// 'n_correct' inizia a contare da 0, quindi gli elementi validi saranno 'n_correct + 1'


if (timer_array != NULL) { // allocazione corretta

// inizializzo il vettore
for (i = 0; i < n_correct + 2; i++, timer_array[i] = 0);


timer_array[0] = n_correct + 2; // salvo numero elemnti dell'array

for (i = 1; i < n_correct + 2; i++)
timer_array[i] = work [i-1]; // copiato l'array con il giusto numero di elementi

free(work); // dealloco 'work'

return timer_array;

} else
return NULL;

} else
return NULL;

} else
return NULL;

}




// FUNZIONE DI STAMPA DELLA GUIDA
void print_error(){
printf("TIMER COUNTDOWN\n\n");
printf("Sintassi: Timer_Countdown time_s [time_s] [time_s] ....\n\n");
printf("Questo programma data una serie di tempi in secondi, fa il coundown sia dei singoli timer che del totale, visualizzando sia il tempo che avanza, sia quello rimanante\n\n\n");
}



Ho postato tutto il codice per completezza, ma il problema è presente nelle istruzioni in grassetto.

Inizio col dire che programmo con XCode 4.5.2 e il problema si presenta con entrambi i compilatori del programma (Apple e GCC).

In sostanza la malloc alloca settori di memoria già precedentemente occupati da 'work'. Questo non si nota a prima vista, dato che il programma si esegue regolarmente, ma con il cambiamento dell'ultimo valore del vettore 'work' dovuto all'assegnazione di
timer_array[0] = n_correct + 2
Ho fatto anche le verifiche sui puntatori degli array che hanno confermato la mia ipotesi.

Volevo sapere se è possibile che questo problema sia generato da errori di codice, oppure da un bug, piuttosto insidioso, di XCode.

stohuman
15-01-2013, 09:43
Mhh ho fatto un piccolo test .. su windows, anche se non dovrebbe cambiare niente (spero :stordita: ).

Apparte il fatto della chiamata system che non ho cambiato per pigrizia, inizialmente ho passato due parametri al programma, crash ovvio.. come si vede glie ne ho passati anche 3 tanto per.. però non crasha se con 1 parametro.

Ora contando che sono sveglio come un albero.. secondo me devi controllare il passaggio dei parametri, forse è quello il problema.

http://oi49.tinypic.com/2yjopwx.jpg

Spero di non aver detto una cessata :D :D, bye.

Spe!
15-01-2013, 11:51
Grazie stohuman per aver provato a testare il codice.

Molto probabilmente il crash era dovuto alla chiusura improvvisa del programma, dato che mi era "sfuggito" un commento di troppo nel comando sleep(1) che scandiva la procedura. :D :D
Corretto il codice, ma il problema dell'allocazione rimane.

Ricordo di aver avuto problemi qualche tempo fa, con alcuni programmi che gestivano percorsi di files da linea da comando; non so però quanto questo possa incidere su semplici argomenti interi.


EDIT: Risolto, mancava il numero dei bytes da allocare nella malloc! :doh: :muro: :cool:

stohuman
16-01-2013, 00:09
EDIT: Risolto, mancava il numero dei bytes da allocare nella malloc! :doh: :muro: :cool:

Vero, l'adorato sizeof()...