Ir para conteúdo
Fórum Script Brasil
  • 0

Erro Com Lista Dinâmica, Comando Free(.)


Guest Fabio Lopes

Pergunta

Guest Fabio Lopes

Boa tarde a todos. O programa, cujo código segue abaixo, é um escalonador de processos(que está sendo estudado na disiplina de Sistemas Operacionais, da faculdade), que processa em ordem de prioridade (do maior para o menor - decrescente). O intervalo de tempo disponível para processar cada processo é digitado pelo usuário, assim como o tempo total de cada execução.

A cada execução, o programa deve executar os processos de maior prioridade, obedecendo os intervalos e o tempo de processamento total. A cada intervalo de processamento, deve ser permitido ao usuário cadastrar novos processos e esses serão reorgranizados de acordo com a prioridade e executado, seguindo os padrões acima, infinitamente.

Um exemplo.

sendo P, um processo. Pri, prioridade. T, Tempo. ID, identificação

P(Pri, T, ID)

Os seguintes processos devem ser processados num tempo total de 10, a cada intervalo de tempo 2, para cada processamento

P(7, 4, A)

P(9, 7, B)

Execução:

P(9, 2, B)

P(9, 4, B)

P(9, 6, B)

P(9, 7, B)

P(7, 2, A)

P(7, 3, A)

Perceba que aqui termina, pois o tempo já é igual a 10, mas faltou executar somente o tempo 1 do processo A

Neste momento, o ucuário entra com um novo processo:

P(8, 3, C)

Então na próxima execução devemos ter:

P(8, 2, C)

P(8, 3, C)

P(7, 1, A)

Agora não há mais processos pendentes, então deve perguntar ao usuário se deseja cadastrar mais, em caso negativo, encerra o programa.

No entanto, para permitir que o usuário cadastre novos processos, estou utilizando a estrutura:


struct EProcesso{
int prioridade; //Prioridade do Processo
int tempo; //Tempo de Execução do Processo
int id; //Id do Processo
};//struct EProcesso
struct Processos{
int tam; //Quantidade de processos
int intervalo; //Intervalo de tempo entre a execução de cada processo
int tempo; //Tempo total de execução do processo
struct EProcesso * elem; //Cadastro dos processos
};//struct Processos
//variáveis globais
struct Processos processo;
[/codebox]

E quando o usuário solicita o cadastramento de um novo processo entre um processamento e outro, utilizao o comando

"free(processo.elem)" para liberar memória e peço para alocar memória em processo.elem, novamente.

O curioso é que na primeira vez em que processo, este código funciona, por exemplo, este exemplo acima citado roda perfeitamente, no entanto se for cadastrar mais um processo, ocorre erro de violação de memória no comando "free(processo.elem)

O compilador é o Borland 5.02

Sei que o problema é um pouco complicado, mas já analisei diversas vezes o código, e não parece haver erro de lógico, estou suspeitando que seja algum erro de sintaxe, já que não tenho muita experiência com o C. Desde já agradeço a atenção.

Meu e-mail é: fabiomirand@globo.com

[codebox]#include <stdio.h>
#include <conio.h>
#include <stdlib.h>

//estruturas
struct EProcesso{
int prioridade; //Prioridade do Processo
int tempo; //Tempo de Execução do Processo
int id; //Id do Processo
};//struct EProcesso

struct Processos{
int tam; //Quantidade de processos
int intervalo; //Intervalo de tempo entre a execução de cada processo
int tempo; //Tempo total de execução do processo
struct EProcesso * elem; //Cadastro dos processos
};//struct Processos

//variáveis globais
struct Processos processo;

//funções
int getnum(void); // função retorna inteiro
struct EProcesso * alocaprocesso(int n); // função alocar vetor de processos
void preenche_processo(void); // preenche cada processo(prioridade e tempo)
void Imprime_Processos(void); // impressão para teste
void Ordena_Processos(void); // ordena processos por ordem de prioridade
void Executa_Escalonador(void); // Executa o escalonador(imprime o processamento e registra na struct
int Conta_Processos(void); // Conta Processos ainda ativos
void Limpa_Processos(void); // Mantém os processos ainda ativos nas primeiras posições da lista
void Inicial(void); // Escalonador

//códigos-fonte dos módulos
int getnum(){
int n;
scanf("%d", &n);
return n;
}//int getnum

struct EProcesso * alocaprocesso(int n){
struct EProcesso * vetor;
vetor = (struct EProcesso *) malloc(sizeof(struct EProcesso)*n); //alocar memória
if (!vetor){
printf("Não foi possível alocar Memória");
return 0;
}// if
return vetor; //retorna o vetor
}//int alocaprocesso

void preenche_processo(int n){
int i;
processo.elem = alocaprocesso(n);
//preenche cada processo
for (i=0; i<n; i++){
printf("##-- Processo %d --##\n", i+1);
printf("Prioridade: ");
processo.elem[i].prioridade = getnum();
printf("Tempo: ");
processo.elem[i].tempo = getnum();
processo.elem[i].id = i+1;
}//for
}//void preenche_processos

void Imprime_Processos(void){ //****impressão para teste
int i;
for (i=0; i<processo.tam; i++){
printf("%d \n", i+1);
printf("Prioridade: %d \n", processo.elem[i].prioridade);
printf("Tempo: %d \n", processo.elem[i].tempo);
printf("ID: %d \n", processo.elem[i].id);
}
}//void Imprime_Processos

void Ordena_Processos(void){
struct EProcesso aux;
int i, j;
for (i=0; i < processo.tam; i++)
for (j=i+1; j < processo.tam; j++){
if (processo.elem[i].prioridade < processo.elem[j].prioridade) {
aux = processo.elem[i];
processo.elem[i] = processo.elem[j];
processo.elem[j] = aux;
};//if
};//for
}//void Ordena_Processos

void Executa_Escalonador(void){

int i; //auxiliar
int tempo_total; //armazena tempo total subtraindo a cada processamento
int ultimo_tempo; //armazena ultimo tempo impresso
struct EProcesso aux;

tempo_total = processo.tempo;
printf("#### EXECUCAO ##### \n");
printf("| Prioridade | Tempo | ID | \n"); //Imprime Cabeçalho
for (i=0; i < processo.tam; i++){ //roda por todos os processos
ultimo_tempo = 0;
aux = processo.elem[i]; //faz aux receber o processo em execução
while ((aux.tempo > 0) && (tempo_total>0)){ //repete até utilizar todo o tempo do processo e tempo de processamento não ter esgotado
if (!(tempo_total < aux.tempo)){ //Tempo total de processamento for maior ou igual que o tempo do processo
if (aux.tempo < processo.intervalo){//Tempo restante do processo, menor que o tempo do intervalo

ultimo_tempo = ultimo_tempo + aux.tempo;
tempo_total = tempo_total - aux.tempo;
printf("| %d | %d | %d | \n", aux.prioridade, ultimo_tempo, aux.id); //imprime processo
aux.tempo=0;
}//if
else{ //Tempo do intervalo menor ou igual ao tempo do processo

ultimo_tempo = ultimo_tempo + processo.intervalo;
tempo_total = tempo_total - processo.intervalo;
printf("| %d | %d | %d | \n", aux.prioridade, ultimo_tempo, aux.id); //imprime processo
aux.tempo = aux.tempo - processo.intervalo;
};//else
}//if
else{ //Tempo restante do processamento é menor que o tempo do processo
if (!(tempo_total > processo.intervalo)){//se tempo total do processamento for menor ou igual ao intervalo
ultimo_tempo = ultimo_tempo + tempo_total;
aux.tempo = aux.tempo - tempo_total;
tempo_total = 0;
printf("| %d | %d | %d | \n", aux.prioridade, ultimo_tempo, aux.id); //imprime processo
}//if
else{//Tempo total do processamento é maior que o intervalo
ultimo_tempo = ultimo_tempo + processo.intervalo;
tempo_total = tempo_total - processo.intervalo;
aux.tempo = aux.tempo - processo.intervalo;
printf("| %d | %d | %d | \n", aux.prioridade, ultimo_tempo, aux.id); //imprime processo
};//else
};//else
};//while
processo.elem[i].tempo = aux.tempo;
};//for
}//void Executa_Escalonador

int Conta_Processos(void){
int qde_processos; //armazena qde de processos conforme processamento
int i; //auxiliar
qde_processos=0;
for (i=0; i < processo.tam; i++){
if (processo.elem[i].tempo)
qde_processos = qde_processos ++ ;
};//for
return qde_processos;
}//void Conta_processos

void Limpa_Processos(void){
int i, j;
for (i=0; i<processo.tam; i++){
if (!(processo.elem[i].tempo)){
for (j=i; j<processo.tam; j++){
if (j != processo.tam-1){
processo.elem[j] = processo.elem[j+1];
};//if
};//for
};//if
};//for
}//void Limpa_Processos

void Inicial(void){
int opcao;
int qde, i;
struct EProcesso * aux;
printf ("Tempo do intervalo de cada processamento = ");
processo.intervalo = getnum();
printf ("Tempo total do processamento = ");
processo.tempo = getnum();
printf ("Quantidade de processos a serem cadastrados = ");
processo.tam = getnum();
preenche_processo(processo.tam);
Ordena_Processos();
do{
Executa_Escalonador();
printf("Pressione qualquer tecla. \n");
getch();
qde = Conta_Processos(); //retorna nº de processos a serem processados
if (qde){
printf("Ainda resta(m) %d Processo(s) a ser(em) processado(s), deseja cadastrar mais?\n", qde);
}//if
else{
printf("Não há mais processos a serem processados, deseja cadastrar novos?\n");
};//else
printf("1 - Sim \n");
printf("0 - não \n");
printf("Opção: ");
opcao = getnum();
if (opcao){ //Cadastramento de novo(s) processo(s)
Limpa_Processos(); //faz os processos ainda ativos serem os primeiros da lista
if (qde){
aux = alocaprocesso(qde); //prepara aux para receber os atuais processos ainda ativos
for (i=0; i<qde; i++){ //armazena os processos ativos em aux
aux[i]=processo.elem[i];
};//for
};//if
printf("Informe a quantidade de novos processos a serem cadastrados: ");
processo.tam = qde + getnum();
free(processo.elem);
processo.elem = alocaprocesso(processo.tam);
preenche_processo((processo.tam - qde)); //preenche somente os novos processos.
if (qde){
for (i=qde; i<processo.tam; i++){
processo.elem[i] = aux[(i-qde)]; //Preenche os processos em aux
};//for
free(aux);
};//if
Ordena_Processos();
};//if

// Imprime_Processos();
// getch();

} while (qde);
}//void inicial

//######---FIM---######

main(){
Inicial();
}//main

Link para o comentário
Compartilhar em outros sites

5 respostass a esta questão

Posts Recomendados

  • 0
free(processo.elem);

processo.elem = alocaprocesso(processo.tam);

preenche_processo((processo.tam - qde)); //preenche somente os novos processos.

voce aloca tudo de uma vez,

quando voce usa o free toda a referencia da sua lista é descartada, então voce não tem mais como chegar a nenhum de seus elementos da lista.

o correto é alocar um elemento da lista por vez.

Link para o comentário
Compartilhar em outros sites

  • 0
Guest Fábio Lopes

Ok, mas como devo fazer isso? Entendi a explicação e foi de muita ajuda para começar a entender o problema, no entanto não entendi como, tecnicamente, devo fazer para alocar um elemento de cada vez.

Desde jpa agradeço.

Saudações,

Fábio Lopes

Link para o comentário
Compartilhar em outros sites

  • 0

para alocar um só elemento é assim:

vetor = (struct EProcesso *) malloc(sizeof(struct EProcesso)); //alocar memória
Agora voce terá uma estrutura de repetição para alocar um por um e terá que armazenar as alocações em diferentes variáveis. O mais comum é criar uma lista encadeada, pois geralmente não sabemos o tamanho exato da quantidade de variaveis. ou se preferir defina uma quantidade assim:
struct EProcesso * aux[100];

Link para o comentário
Compartilhar em outros sites

  • 0
Guest Fábio Lopes

É... foi mal.. logo depois que escrevi que não havia entendido, ficou claro para mim que deveria ter usado uma lista simplesmente encadeada e acabei me eskecendo de postar aqui. Acontece que durante a codificação não imaginei deparar-me com esta situação. Mas serviu de aprendizado, e muito trabalho para passar tudo para lista encadeada. Valeu pelo auxílio foi de muita ajuda.

Cordialmente,

Fábio Lopes.

Link para o comentário
Compartilhar em outros sites

Participe da discussão

Você pode postar agora e se registrar depois. Se você já tem uma conta, acesse agora para postar com sua conta.

Visitante
Responder esta pergunta...

×   Você colou conteúdo com formatação.   Remover formatação

  Apenas 75 emoticons são permitidos.

×   Seu link foi incorporado automaticamente.   Exibir como um link em vez disso

×   Seu conteúdo anterior foi restaurado.   Limpar Editor

×   Você não pode colar imagens diretamente. Carregar ou inserir imagens do URL.



  • Estatísticas dos Fóruns

    • Tópicos
      152,2k
    • Posts
      652k
×
×
  • Criar Novo...