View Single Post
Old 15-01-2013, 09:58   #1
Spe!
Member
 
L'Avatar di Spe!
 
Iscritto dal: Jan 2013
Messaggi: 38
[C] Problema allocazione memoria dinamica (Risolto)

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

Codice:
//
// 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
Codice:
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.

Ultima modifica di Spe! : 15-01-2013 alle 13:24. Motivo: Eliminazione commento
Spe! è offline   Rispondi citando il messaggio o parte di esso