Obter a memória total do computador em C [RESOLVIDO]

1. Obter a memória total do computador em C [RESOLVIDO]

Renan Novaes
zerotres

(usa Outra)

Enviado em 21/05/2013 - 23:43h

As funções malloc, realloc, calloc e free permitem fazer alocação dinâmica. No entanto, gostaria de obter um controle maior sobre a alocação no meu programa e preciso saber o total da memória disponível de forma que eu consiga manter a portabilidade entre sistemas. Existe uma função padronizada? Como posso fazer isso em C?


  


2. MELHOR RESPOSTA

Paulo
paulo1205

(usa Ubuntu)

Enviado em 22/05/2013 - 06:17h

Tanto o padrão da linguagem C (e também o de C++) quanto a biblioteca padrão fazem muito poucas exigências e assunções sobre características da máquina ou do SO em que os programas escritos em C podem executar. De seu ponto de vista, um programa conforme deve executar de modo absolutamente idêntico num super mainframe, num PC parrudão, numa máquina teórica com memória infinita, num micrinho de 8 bits antigo ou por um aluno aplicando o "método do chinês" com a ajuda do seu caderno. Supõe-se pouco além de uma entidade capaz de executar as instruções e alguma forma de memória que possa sofre acessos de leitura e gravação e que permita operações indiretas por meio de ponteiros. Quando se fala em limites (e mais nos requisitos da biblioteca padrão do que características da linguagem em si), geralmente são limites mínimos para que as algumas funções possam executar com conforto.

"Comum a todos os sistemas", portanto, é algo que não vai existir em C puro, pois cada sistema funciona de um jeito e tem API diferente de outros sistemas. No máximo, se você optar por uma biblioteca que esconda particularidades do SO, vai transferir para essa biblioteca do "trabalho sujo" de fazer encadeamentos de #ifdef.

Se existe uma maneira "padrão" de testar a memória disponível para um programa, talvez seja fazer um loop que vai alocando memória sem parar, acumulando o total já alocado, até que uma tentativa de alocação venha a dar erro, de modo mais ou menos parecido com a função alloc_max() do programa abaixo.

/*
Programa de teste de alocacao maxima de memória
usando apenas C padrão (conforme ISO C99).
*/

#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

size_t alloc_max(size_t chunk_size){
void *old_p, *new_p;
size_t total;

if(chunk_size<sizeof(size_t)){
fprintf(stderr, "O tamanho minimo do bloco deve ser de %zu bytes.\n", sizeof(size_t));
return 0;
}

total=0;
old_p=NULL;
while((new_p=malloc(chunk_size))!=NULL){
total+=chunk_size;
/*
XXX: Preenche memória alocada (para forçar seu uso efetivo em sistema com lazy allocation.
Por isso, aliás, a restrição de tamanho mínimo, imposta acima.
*/
memset(new_p, rand(), chunk_size);

/* Guarda o endereço do bloco anterior no começo do novo bloco, para poder desalocar depois. */
*(size_t **)new_p=old_p;
old_p=new_p;
}

for(new_p=old_p; new_p!=NULL; new_p=old_p){
old_p=*(void **)new_p;
free(new_p);
}

return total;
}

int main(void){
size_t chunk, max;
for(chunk=4096; chunk<SIZE_MAX/32+1; chunk*=16){
max=alloc_max(chunk);
printf("Total de %zu bytes (%zu blocos de %zu bytes).\n", max, max/chunk, chunk);
}
return 0;
}


No entanto, quando eu testei esse programa na minha máquina (um notebook com 4GiB de RAM e 6GiB de swap com Ubuntu de 64 bits), ele realmente saiu comendo memória feito um louco mas, quando estava chegando perto de 8GiB, em lugar de receber erro de alocação, ele foi abortado pelo SO, com a seguinte mensagem de erro do kernel (obtida a partir da saída do comando dmesg).

[1376327.747104] Out of memory: Kill process 19883 (a.out) score 810 or sacrifice child
[1376327.747108] Killed process 19883 (a.out) total-vm:8301144kB, anon-rss:3373256kB, file-rss:4kB


O programa acima talvez tivesse funcionado noutro sistema, ou mesmo na minha própria máquina se não houvesse outros processos em execução, competindo com ele pela alocação de memória. Mesmo assim, como se usou apenas C puro, não se tem, por exemplo, distinção entre memória física e memória virtual (tudo é memória), nem interessa se o desempenho vai ficar sofrível. Também não se tem controle sobre eventuais restrições impostas pelo ambiente de execução, como a atribuição de um limite na quantidade de memória que poderá ser usada pelo processo, ou eventuais efeitos de outros processos sobre o ambiente de execução -- afinal, o C padrão não tem a menor ideia de o que seja um processo.

Note ainda, no comentário marcado com "XXX", que uma característica de alocação particular de uma implementação (usada por padrão pela glibc no Linux, mas não obrigatória de modo algum num sistema qualquer -- incluindo o próprio Linux) implica a geração de código artificioso para fazer com que o programa efetivamente use a memória que pediu ao sistema para poder usar.

3. Isso depende muito do Sistema Operacional

Alexandre Mulatinho
mulatinho

(usa Slackware)

Enviado em 22/05/2013 - 00:22h

Vai depender muito do SO, no caso do Linux, o jeito mais fácil seria assim:

No terminal:

$ Mem=`egrep MemTotal /proc/meminfo | awk '{print $2}'` && echo Memoria: $(($Mem/1024))MB
Memoria: 11972MB


ou em C

#include <stdio.h>

int main(void)
{
FILE *fp;
char buffer[1024];

if ((fp = fopen("/proc/meminfo", "r"))) {
fgets(buffer, sizeof(buffer)-1, fp);
fprintf(stdout, buffer);

fclose(fp);
}
}


No Windows já seria de outra forma, espero que ajude!


4. Re: Obter a memória total do computador em C [RESOLVIDO]

Renan Novaes
zerotres

(usa Outra)

Enviado em 22/05/2013 - 00:41h

Obrigado pela resposta, no entanto eu preciso de um método comum entre todos os sistemas. Conheço os dois métodos no Linux. Estou evitando colocar no código aquelas definições do tipo: #ifdef WIN32 ou sei lá oque... faça isso, senão faz aquilo. Quero um sistema abrangente.


5. Re: Obter a memória total do computador em C [RESOLVIDO]

???
gokernel

(usa Linux Mint)

Enviado em 22/05/2013 - 05:57h

E para windows:

http://www.msdn.microsoft.com/en-us/library/windows/desktop/aa366589(v=vs.85).aspx

E se quiser fazer para windows/linux vai precisar daquela parada tipo:

#ifdef ___WIN32___
// bla bla bla
#endif

OBS: o link ficou quebrado ... copiar e colar no navegador o link completo ...


6. Re: Obter a memória total do computador em C [RESOLVIDO]

Renan Novaes
zerotres

(usa Outra)

Enviado em 22/05/2013 - 12:02h

Obrigado Paulo e GoKernel. Estava evitando escrever algo como postado acima. Pensei exatamente em testar a quantidade de memória total usando esse tipo de alocação, no entanto se eu tivesse pensado mais um pouco, ia determinar que a memória é administrada pelo Sistema Operacional, de forma que não há como padronizar a obtenção desses dados em código sem superficialidade. Cheguei naquele momento em que meu projeto precisa escolher um sistema e vou de Linux mesmo. Obrigado a todos.
Afinal Paulo, testei o código no meu computador e fica meio grotesco implementar isso, como você mesmo já sabia.
Acho que vou buscar recursos no /proc/meminfo conforme sugerido na postagem do mulatinho.

Obrigado a todos.






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts