Você está na página 1de 5
Projeto de Algoritmos | LinguagemC | indice Alocacao dinamica de memoria ‘As declaragdes abaixo alocam espaco na meméria para algumas varidveis. A alocacdo 6 estitica , ou seja, acontece antes que © programa comece a ser executado: char ¢; int i; int v[10]; Em muitas aplicagdes, a quantidade de meméria a alocar s6 se torna conhecida durante a execugao do programa. Para lidar com essa situacao € preciso recorrer a alocacao dinfimica de meméria, A alocacao dinamica é administrada pelas fungdes malloc, realloc e free, que esto na biblioteca std1ib. Para usar essa biblioteca, inclua a correspondente interface no seu programa: include A funcao malloc A funcdo malloc (0 nome é uma abreviatura de memory allocation) aloca espaco para um bloco de bytes consecutivos na memoria RAM (= random access memory) do computador e devolve o endereco desse bloco, O ntimero de bytes ¢ especificado no argumento da funcao. No seguinte fragmento de cédigo, nal loc aloca 1 byte: char *ptrs ptr = malloc (1); seanf (°%c", ptr); O enderego devolvido por malloc é do tipo genérico void *. © programador armazena esse endereco num ponteiro de tipo apropriado, No exemplo acima, 0 endereco é armazenado no ponteiro ptr, que é do tipo ponteiro-para-char. A transformacao do ponteiro genérico em ponteiro-para-char é automatica; ndo é necessdrio escrever ptr = (char *) malloc (1); A fim de alocar espaco para um objeto que precisa de mais que 1 byte, convém usar 0 operador sizeof, que diz quantos bytes 0 objeto em questao tem: typedef struct { int Gia, mes, ano; } data; data *d; d= malloc (sizeof (data)); d-rdia = 31; d->mes = 12; d->ano = 20165 Note que sizeof ndo é uma funcao mas um operador, tal como return, por exemplo, Os parénteses na expressio sizeof (data) sao necessérios porque data ¢ um tipo-de-dados (os parénteses sao anélogos aos do casting). © operador sizeof também pode ser aplicado diretamente a uma variavel: se var é uma variével entéo sizeof var ¢ 0 nimero de bytes ocupado por var. Poderiamos ter escrito d = malloc (sizeof *4) no exemplo acima, c caractere ASCII. V= malloc (10 * sizeof (int))s x = malloc (10 * sizeof *); A funcao free As variaveis alocadas estaticamente dentro de uma fungao, também conhecidas como varidveis automiticas ou locais, desaparecem assim que a execugao da funcao termina. Jé as variaveis alocadas dinamicamente continuam a existir mesmo depois que a execucao da funcao termina. Se for necessario liberar a meméria ocupada por essas varidveis, é preciso recorrer a fungao free. A fungao free desaloca a porcdo de meméria alocada por malloc. A instrucio free (ptr) avisa ao sistema que o bloco de bytes apontado por ptr esta dispontvel para reciclagem. A proxima invocacao de malloc poder tomar posse desses bytes. Nao aplique a funcao free a uma parte de um bloco de bytes alocado por malloc (ou realloc). Aplique free apenas ao bloco todo. int "v5 vi= malloc (100 * sizeof (int)); v[e] = 999; free (v03)5 int *prinos (void) ¢ int v[3}3 v[@} = 1809; v{2} = 1013; v{2) = 1019; retuen v5) sta encadeada 1st fla tacrescentacabeca (celula *Ist) celula cabecas abeca.prox = 1st return acabecs; } int *p, ea jailoe (sizeoF (Ant))s 1235 alloc (sizeof (Ant))3 05, free (9)5 Free (4); // mi Adeia @ = MULL; // boa Sdeia Vetores e matrizes Eis como um velar (= array) com n elementos inteiros pode ser alocado (e depois desalocado) durante a execugao de um programa: int “vs int nj ‘seanf ("%d", fin); v = malloc (n * sizeof (int)); for (int 1 = 0; 1 < nj eed) seanf (°%d", @v[i])5 free (v)3 (A propésito, veja a observacdo sobre enderecos e vetores no capitulo Enderecos e ponteiras.) Do ponto de vista conceitual, mas apenas desse ponto de vista, a instrugao malloc (100 * sizeof (int)); tem efeito andlogo ao da alocacio estatica int v[10@]3 Matrizes. Matrizes bidimensionais sao implementadas como vetores de vetores, Uma matriz.com m linhas ¢ n colunas é um. vetor de m elementos cada um dos quais ¢ um vetor de n elementos, O seguinte fragmento de c6digo faz. a alocagao dinamica de uma tal matriz: int "4H; N= malloc (m * sizeof (int *)); for (int i= @; i < mj ++i) [i] = malloc (n * sizeof (int)); Portanto, M[1][4] 0 elemento de m que esté no cruzamento da linha i com a coluna j. 4 Redimensionamento e a funcio realloc As vezes 6 necessario alterar, durante a execucao do programa, o tamanho de um bloco de bytes que foi alocado por malloc. Isso acontece, por exemplo, durante a leitura de um arquivo que se revela maior que o esperado, Nesse caso, podemos recorrer a funcao real loc para redimensionar o bloco de bytes. ‘A funcdo realLoc recebe o endereco de um bloco previamente alocado por malloc (ou por real loc) e o niimero de bytes que © bloco redimensionado deve ter. A funcao aloca 0 novo bloco, copia para ele o contetido do bloco original, e devolve 0 enderego do novo bloco. Se o novo bloco for uma extensao do bloco original, seu enderego ¢ 0 mesmo do original (¢ 0 contetido do original nao precisa ser copiado para o novo). Caso contratio, real loc copia o contetido do bloco original para o novo e libera 0 bloco original (invocando free). A propésito, o tamanho do novo bloco pode ser menor que o do bloco original. Suponha, por exemplo, que alocamos um vetor de 1089 inteiros e depois decidimos que precisamos de duas vezes mais espaco. Veja um caso concreto: int *v; V = malloc (1008 * sizeof (int); for (int i= 0; i < 990; i++) seanf ("%d", &v[i])3 v = realloc (v, 2000 * sizeof (int)); for (int 1 = 990; 1 < 2008; i+) scanf ("%d", &v[i]); Nesse exemplo, poderiamos usar a seguinte implementacao ai hoe de realoc: int *realloc (int *v, unsigned int N) ( int *novo = malloc (N); for (int 1 = 0; 1 < 1000; i++) novo i] = v{i]s free (v); return novos y E claro que a implementacdo de realloc na biblioteca std1ib é mais geral e mais eficiente. arquivo de texto A meméria é finita ‘Se a memoria do computador ja estiver toda ocupada, mal loc nao consegue alocar mais espago ¢ devolve NULL. Convém verificar essa possibilidade antes de prossegui ptr = malloc (sizeof (data)); BF (ptr == MULL) { paintt ("Soconro! malloc devolveu NULL!\n"); exit (EXIT FAILURE); y A digitacdo frequente e repetida desse teste ¢ cansativa. Por isso, usaremos, neste sitio, a seguinte funcdo-embalagem (€ wrapper function) de malloc: void tmalloce (size_t nbytes) ( void *ptrs ptr = malloc (nbytes); Af (ptr == NULL) { printf ("Socorro! malloc devolveu NULLI\n"); exit (EXIT_FAILURE); y return ptes > (© parametro de malloc ¢ do tipo size_t (abreviatura de size data type); em muitos computadores, size_t € 0 mesmo que unsigned int. a mesma forma, podemos preparar uma funcdo-embalagem realocc para cuidar das situagdes em que realloc devolve NULL, Perguntas e respostas + Prrcunra: fi verdade que néo convém alocar blocos de poucos bytes, ou seja, invocar malloc com argumento muito pequeno? Risposta: Cada invocagéo de malloc aloca um bloco de bytes maior que o solicitado; os bytes adicionais s4o usados para guardar informacées administrativas sobre o bloco (essas informacies permitem que o bloco seja corretamente desalocado, mais tarde, pela fungdo free). Assim, néo é eficiente alocar blocos muito pequenos repetidamente; é melhor alocar um bloco grande e dele retirar pequenas porgées na medida do necessério. A boa noticia é que o programador nao precisa fazer isso pessoalmente pois malloc implementa essa politica "por baixo do pano" sem que o programador perceba, ‘+ Puxcunta: Posso alocar um vetor estaticamente com numero nao-constante de elementos? Por exemplo, posso dizer int vin)s den s6 se torna conhecido durante a execucéo do programa? Risposta: Nao é uma boa ideia, + Prncuvra: f verdade que devemos atribiuir WLL a cada ponteiro que se toriou inal ou desnecessério? Risposta: Sim, Convém ndo deixar ponteiros "soltos! (= dangling pointers) no seu programa, pois isso pode dificultar a depuragao do programa e pode ser explorado por hackers para atacar o seu computador. Portanto, depois de cada free (ptr), atribua NULL a ptr: foe (ptr); ptr = NULL; (Atibuir um valor a uma variavel que ndo sera mais usada € decididamente deselegante, mas ndo ha como lidar com hackers de ‘maneira elegante...) Para nao cansar o leitor com detalhes repetitivos, este sitio ignora essa recomendagao de seguranca. + Pracunta: E verdade que deveriamos usar a funcéo calloc no lugar de malloc? Resrosta: Talvez. A chamada calloc (a, b) aloca um bloce de a*b bytes ¢atrit calloc exist? de Nathaniel J. Smith (2016) ses bytes. Veja o artigo lulia's drawings: Memory allocation. Veja Memory Layout of C Programs em GeeksforGeeks. Valgrind: ferramenta para encontrar vazamentos de meméria (= memory leaks) e segmentation faults no seu programa. ‘Ahualizado em 2018-05-29 hitpsi//wiwwime.usp.br/~pt/algortmos/ Paulo Feo DecMélise

Você também pode gostar