I'm writing a service in Linux using c, so I need to keep the memory usage stable. But after tracing a day, the memory raise. If I monitor from the System Monitor in Linux, it raise 1M and the mem%(0 -> 0.1). In pmap command, it raise 1M, too.
I have use valgrind to check if there are any memory leak, and it report none if I run once. If I start the service and use valgrind, it will report that I free invalid pointer. So, I think it should have something to do about my pointer.
struct list {
int no;
BYTE parm[SLEN];
struct list *next;
};
struct list *memory_current;
struct list *memory_head;
struct list *memory_prev;
int getMemoryUsage(int sendCmd) {
pthread_mutex_lock(&lock);
FILE *fp = NULL;
BYTE buffer[10] = "";
BYTE memorys[10] = "";
int flag = 0;
TRY {
if ((fp = popen("free_data=$(free -m | grep Mem);total=$(echo $free_data | cut -f2 -d' ');"
"free_data=$(free -m | grep 'buffers/cache');buffers=$(echo $free_data | cut -f3 -d' ');echo $(($buffers*100/$total))", "r")) == NULL) {
THROW(CMD_NOT_FND);
}
else {
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
strcat(memorys, buffer);
memory_current = (struct list *)malloc(sizeof(struct list));
if (memory_current == NULL) {
THROW(MALLOC_ERROR);
}
memory_current->next = NULL;
strncpy(memory_current->parm, buffer, SLEN -1);
memory_current->parm[SLEN -1] = '\0';
if (memory_head == NULL)
memory_head = memory_current;
else
memory_prev->next = memory_current;
memory_prev = memory_current;
memset(buffer, 0, sizeof(buffer));
flag = 1;
}
if (flag == 0)
THROW(CMD_NOT_FND);
}
}
CATCH (CMD_NOT_FND) {
memorys[0] = 'n';
memorys[1] = '/';
memorys[2] = 'a';
printf("Memory Usage % : %s\n", memorys);
printLog("Memory Usage % ->", memorys);
}
CATCH (MALLOC_ERROR) {
memorys[0] = 'n';
memorys[1] = '/';
memorys[2] = 'a';
printf("Memory Usage malloc error : %s\n", memorys);
printLog("Memory Usage malloc error ->", memorys);
}
FINALLY {
pclose(fp);
// printf("Memory Usage % : %s\n", memorys);
// printf("Memory Usage length %d\n", strlen(memorys));
}
ETRY;
if (sendCmd == 1) {
if (flag != 0) {
memory_current = memory_head;
int totalMemory = 0;
int count = 0;
int avg = 0;
int perc = 0;
BYTE avg_memory[10] = "";
while (memory_current != NULL) {
sscanf(memory_current->parm, "%d", &perc);
totalMemory += perc;
memory_current = memory_current->next;
count++;
}
avg = totalMemory / count;
snprintf(avg_memory, sizeof(avg_memory), "%d", avg); ;
strcat(avg_memory, ";");
printf("Memory Usage % : %s\n", avg_memory);
printLog("Memory Usage % ->", avg_memory);
// free linked list
memory_current = memory_head;
while (memory_current != NULL) {
memory_prev = memory_current;
memory_current = memory_current->next;
free(memory_prev);
memory_prev = NULL; //fix dangling
}
head_memory = NULL; //fix dangling
current_memory = NULL; //fix dangling
}
}
pthread_mutex_unlock(&lock);
return 0;
}
I have the global pointer to keep record the memory usage in a timer, and I will use the result and clear the list in a interval of time. I use the same way to use in other function and the memory usage is fine, but the pointers are local and will free at the end.
Could you please help to advice or pointer out what is wrong about my pointer usage. Thanks.
[Update] I found that this might be a dangling pointer, so I set the pointer to NULL after the free. So far the memory won't raise, but I'll keep watching it for more days.
Solved
The memory won't raise again, so I guess it's the dangling pointer issue.