0

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.

Community
  • 1
  • 1
sowrdking
  • 229
  • 1
  • 3
  • 12
  • [Please don't cast the return value of `malloc()` in C](http://stackoverflow.com/a/605858/28169). Also, that looped `strcat(memorys, buffer);` seems very dangerous and likely to overflow. – unwind Mar 07 '14 at 10:21
  • 1
    Please accept the answer that helped you instead of editing your post to add [solved]. – Mauren Mar 10 '14 at 01:58
  • Hi Mauren, The problem is dangling pointer that I solved by myself. – sowrdking Mar 11 '14 at 05:44

1 Answers1

0

memory_current, memory_head and memory_prev were not initialized to NULL.

you check:

 if (memory_head == NULL)

when memory_head was not initialized, therefore you maybe loose some memory allocations

also look like they should be local variables, not global.

SHR
  • 7,940
  • 9
  • 38
  • 57