Skip to content

Instantly share code, notes, and snippets.

@ajithbh
Last active April 24, 2023 00:38
Show Gist options
  • Save ajithbh/8154257 to your computer and use it in GitHub Desktop.
Save ajithbh/8154257 to your computer and use it in GitHub Desktop.
Available memory using C
void mem_avail(void)
{
char *cmd = "awk '{ if (NR == 2) { print $4 }}' /proc/meminfo";
FILE *cmdfile = popen(cmd, "r");
char result[256] = { 0 };
while (fgets(result, sizeof(result), cmdfile) != NULL) {
printf("%s\n", result);
}
pclose(cmdfile);
}
// Alternately for free memory and other info
//------------------------------------------
#inclde <sys/sysinfo.h>
int sysinfo(struct sysinfo *info);
struct sysinfo {
long uptime; /* Seconds since boot */
unsigned long loads[3]; /* 1, 5, and 15 minute load averages */
unsigned long totalram; /* Total usable main memory size */
unsigned long freeram; /* Available memory size */
unsigned long sharedram; /* Amount of shared memory */
unsigned long bufferram; /* Memory used by buffers */
unsigned long totalswap; /* Total swap space size */
unsigned long freeswap; /* swap space still available */
unsigned short procs; /* Number of current processes */
unsigned long totalhigh; /* Total high memory size */
unsigned long freehigh; /* Available high memory size */
unsigned int mem_unit; /* Memory unit size in bytes */
char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding to 64 bytes */
};
unsigned long mem_avail()
{
struct sysinfo info;
if (sysinfo(&info) < 0)
return 0;
return info.freeram;
}
@Souravgoswami
Copy link

Souravgoswami commented Jan 22, 2021

You forgot to multiply info.freeram with info.mem_unit.

I have a raspberry Pi to test that. I have Rapsberry Pi 3 Model B.

The info.mem_unit is 4096 there (pagesize). The totalram is returned 205226, but if I multiply it with mem_unit, it then returns 840605696, when 1024 is divided with that, it agrees with /proc/meminfo's memtotal, which is 820904 kB.

But on my PC 64 Bit, genymotion VM Android (32 Bit), other VMs, Heroku, Codeanywhere, my laptop and my laptop's VM, the mem_unit is 1. But it's to keep in mind whenever the unsigned long overflow happens.

Edit

The reason is that, well on 32 bit systems, the integer overflow can happen quite easily. If integer overflows, the mem_unit is set to something. Say on my raspberry Pi, I have 1 GB RAM, and for the sake of testing, I allocated 32 GB swap (zram), and then the integer overflow should happen, but the mem_unit is set to pagesize to prevent that.

For example:

Screenshot from 2021-01-23 23-43-51

Code used:

#include <stdio.h>
#include <sys/sysinfo.h>

int main() {
	struct sysinfo i ;
	short status = sysinfo(&i) ;
	if (status < 0) return 1 ;
	
	printf(
		"\e[1;38;2;0;200;0m"
		"Mem Unit: %u\e[0m\n",
		i.mem_unit
	) ;
}

A user can have 10000 GB RAM, in such case, even unsigned long long int will overflow. There, you can use mpz_t, GMP bignum library, or the MPFR arbitrary precision float library. During using printf, get string from them, because there's no way to represent such big numbers with C datatypes.

@mikkorantalainen
Copy link

mikkorantalainen commented Jul 20, 2022

A user can have 10000 GB RAM, in such case, even unsigned long long int will overflow.

10000 GB RAM would be "only" 10000 × 1024 × 1024 × 1024 = 1,07×10¹³ bytes but unsigned long long int can contain numbers up to 2^64-1 or about 1,84×10¹⁹ so that would definitely overflow long long int.

If you have more than 10000 EB RAM, then you would need to be more careful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment