簡體   English   中英

使用Windows解決GTK + /隊列中的內存泄漏

[英]Addressing memory leak in GTK+ / Queue with windows

我在Windows中嘗試GTK應用程序,現在才開始學習GTK。

GTK版本:

gtk+-bundle_2.24.10-20120208_win32

申請要求:

1.  Multi threaded
2.  Queue based communication
3.  GTK window to update a image data in screen with 5 secs delay

應用功能:

1.  2 thread (producer and other consumer)
    Producer will post a string to queue manager which will form a structure and post the data to the respective queue
2.  Upon posting the data to the queue manager producer thread shall update the respective image on the screen
3.  Consumer will be monitoring the queue and on receiving data consumer will process the data according

The application is running as expected:

我在這里面臨的問題是內存(根據Windows資源監視器)

Confused which one is causing the LEAK -- GTK or my queue or ???

    the program starts with 26K memory and on certain time it reaches 190000K memory. So i see memory leak
    request some guidance in handling this issue

這是我正在工作的示例程序流程。

#include <stdio.h>
#include <glib.h>
#include <gtk/gtk.h>
#include <windows.h>

#define sleep(n) g_usleep(1000 * n)

G_LOCK_DEFINE_STATIC (queue_memchunk);
static GMemChunk   *queue_memchunk = NULL;
static GTrashStack *free_queue_nodes = NULL;
GQueue* msgQueueId[7];


#define NORMAL_TEXT     0
#define WARNING_TEXT    1
#define STATUS_TEXT     2
#define NORMAL_FONT     0
#define SMALL_FONT      1
#define NORM_FONT_UNLTD 2
#define MAX_MSG_SIZE        5120
#define TRACK_ONE_SIZE      150
#define TRACK_TWO_SIZE      100
#define TRACK_THREE_SIZE    100
#define FSM_CHANNEL     1



typedef struct
{
    int msgType;
    int msgSize;
    char msgBuf[MAX_MSG_SIZE];
}STRUCT_MSG;

GtkWidget* window;

struct WidgetsAlive
{
    GtkWidget* widPtr;
    int widIndex;
    struct WidgetsAlive* dependants;
    struct WidgetsAlive* next;
};

/* Linked list ptr to the widgets alive */
static struct WidgetsAlive* wAlive = NULL;
static struct WidgetsAlive* depFirstNode = NULL;
typedef struct {
    char* fileName;
    }dispTextPage_struct;

    typedef struct {
        char* data;
         int row;
         int column;
        char textType;
        char fontType;
        }updateTextPage_struct;

int waitForLoop;

void dispInit(int argc, char* argv[]);
void dispInfoPage(char* fileName, int duration);
gboolean dispTextPage_callBack(dispTextPage_struct *params);
int dispTextPage(char* fileName, int duration);


int destroyNotify(void){
    printf("Notfiy called in");
    while (gtk_events_pending())
          {
            g_usleep (1);
            gtk_main_iteration_do(FALSE);
          }
    waitForLoop = 0;
    return 0;

}


gpointer main_callback(gpointer data)
{
    gtk_main();
    return 0;
}

void dispInit(int argc, char* argv[])
{
    printf("Initializing the display library\n");
    gtk_init(&argc, &argv);
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_resize(GTK_WINDOW(window), 640, 480);
    gtk_window_set_default_size(GTK_WINDOW(window), 640, 480);
    gtk_widget_realize( window );
    gtk_window_set_decorated(GTK_WINDOW(window), FALSE);
    g_thread_create(main_callback, NULL, FALSE, NULL);
}

void dispInfoPage(char* fileName, int duration)
{
    int index;
    gdk_threads_enter();
    destroyWidget(0);
    GtkWidget *image;
    image = gtk_image_new_from_file(fileName);
    gtk_container_add(GTK_CONTAINER(window), image);
    gtk_widget_show(image);
    gtk_widget_show(window);
    gdk_threads_leave();
}

struct WidgetsAlive* getWidgetFromList(int widgetIndex)
{
        struct WidgetsAlive *temp, *prev;
        temp = wAlive;
        prev = NULL;
        if (temp == NULL)
        {
                /* Widget list is empty. Nothing to destroy */
                return NULL;
        }
        else
        {
            while(temp != NULL)
            {
                if(temp->widIndex == widgetIndex)
                {
                        return temp;
                }
                else
                {
                        //printf("Iterating to the next widget in the list, since the index is different\n");
                        prev = temp;
                        temp = temp->next;
                }
             }
        //printf("No widget with index %d found to destroy, Please check the index..\n", index);
        }
    return NULL;
}

int destroyWidget(int index)
{
    GList *children, *iter;
        struct WidgetsAlive *temp, *prev, *next, *depTemp;
        temp = wAlive;
        prev = wAlive;
        gtk_window_resize((GtkWindow*)window, 800, 600);
        children = gtk_container_get_children(GTK_CONTAINER(window));
        for(iter = children; iter != NULL; iter = g_list_next(iter)){
            gtk_container_remove(GTK_CONTAINER(window),GTK_WIDGET(iter->data));
            //printf("Deleting Widget\n");
        }
        g_list_free(iter);
        g_list_free(children);

    gtk_window_resize((GtkWindow*)window, 800, 600);
  /*  if (temp == NULL)
    {
        return;
    }
    else
    {
        if (temp->widIndex == index)
        {
            if (temp->widPtr != NULL)
            {
                if (GTK_IS_WIDGET(temp->widPtr))
                {
                    //gtk_widget_destroy((GtkWidget*)temp->widPtr);
                    printf("Destroying widget Done\n");
                }
            }
            depTemp = depFirstNode;
            next = depFirstNode;
            while (depTemp != NULL)
            {
                depTemp = depTemp->next;
                free(next);
                next = NULL;
                next = depTemp;
            }
            depFirstNode = NULL;
            wAlive = NULL;
            free(temp);
            temp = NULL;
            return;
        }
        else
        {
            while(temp != NULL)
            {
                if(temp->widIndex == index)
                {
                    printf("Found widget match\n");
                    if (temp->widPtr != NULL)
                    {
                        if (GTK_IS_WIDGET(temp->widPtr))
                        {
                            //gtk_widget_destroy((GtkWidget*)temp->widPtr);
                        }
                    }
                    prev->next = temp->next;
                    free(temp);
                    temp = NULL;
                    return;
                }
                else
                {
                    prev = temp;
                    temp = temp->next;
                }
            }
        }
    }*/
}


int addToWidgetsAlive(GtkWidget* inWidget, struct WidgetsAlive* dependants)

{
    /*struct WidgetsAlive *temp, *node;
    node = (struct WidgetsAlive*)malloc(sizeof(struct WidgetsAlive));
    node->widPtr = inWidget;
    node->widIndex = 1;
    if (dependants != NULL)
        node->dependants = dependants;
    else
        node->dependants = NULL;
    node->next = NULL;
    if (wAlive == NULL)
    {
        wAlive = node;
    }
    else
    {
        temp = wAlive;
        while(temp->next != NULL)
        {
            temp = temp->next;
        }
        node->widIndex = temp->widIndex + 1;
        temp->next = node;
    }
    return node->widIndex;*/
    return 0;
}

int dispTextPage(char* fileName, int duration)
{
//dispTextPage_struct *params;
    dispTextPage_struct *params;
    params = (dispTextPage_struct*)malloc(sizeof(dispTextPage_struct));
    params->fileName = fileName;
    /*
    memset(&params2,'\0',sizeof(dispTextPage_struct));
    params2.fileName = fileName;*/
    while(gtk_events_pending()){
        gtk_main_iteration_do(FALSE);
        g_usleep(1000);
    }
    printf("Gidel added \n");
    waitForLoop=1;
    g_idle_add_full(G_PRIORITY_DEFAULT_IDLE,dispTextPage_callBack,params,destroyNotify);
    while(waitForLoop == 1){
        g_usleep(1000);
    }
    free(params);
}


gboolean dispTextPage_callBack(dispTextPage_struct *params)
{
    char* fileName = params -> fileName;
    int index;
    int isJustifyCenter = 0;

    GtkWidget *textv;
    GdkWindow *textv_window;
    GdkPixmap *pixmap;
    GtkTextBuffer* textBuffer;
    GdkColor color;
    printf("\ntextpage :,1\n");
    destroyWidget(0);
    textv = gtk_text_view_new ();
    gtk_text_view_set_left_margin(GTK_TEXT_VIEW(textv), 22);
    gtk_text_view_set_right_margin(GTK_TEXT_VIEW(textv), 20);
    gtk_text_view_set_pixels_above_lines(GTK_TEXT_VIEW(textv),1);
    gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(textv), GTK_WRAP_CHAR);
    if (isJustifyCenter == 1)
    {
        gtk_text_view_set_justification(GTK_TEXT_VIEW(textv), GTK_JUSTIFY_CENTER);
    }
    else
    {
        gtk_text_view_set_justification(GTK_TEXT_VIEW(textv), GTK_JUSTIFY_LEFT);
    }

    gtk_text_view_set_editable(GTK_TEXT_VIEW(textv), FALSE);
    gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(textv), FALSE);

    gtk_container_add(GTK_CONTAINER(window), textv);
    printf("\ntextpage :,3\n");
    textv_window = gtk_text_view_get_window (GTK_TEXT_VIEW (textv),GTK_TEXT_WINDOW_TEXT);
    gdk_color_parse ("#68604d", &color);
    pixmap = gdk_pixmap_create_from_xpm ((GdkDrawable *) textv_window, NULL,&color, fileName);
    printf(" textpage :,4\n");
    gdk_window_set_back_pixmap (textv_window, pixmap, FALSE);
    g_object_unref(pixmap);
    textBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textv));
    gtk_text_buffer_create_tag (textBuffer, "bold","foreground", "Black", NULL);
    gtk_text_buffer_create_tag (textBuffer, "Redbold","foreground", "Red",NULL);
    gtk_text_buffer_create_tag (textBuffer, "fontSize","font", "saxmono 20",NULL);
    gtk_text_buffer_create_tag (textBuffer, "smallFontSize", "font", "saxmono 14", NULL);
    gtk_text_buffer_create_tag (textBuffer, "fontweight","weight", 1000,NULL);
    index = addToWidgetsAlive(textv, NULL);
    gtk_widget_show(textv);
    gtk_widget_show(window);
//free(params);
return 0;
}
gboolean updateTextPage_callBack(updateTextPage_struct *params)
{
    char* data = params -> data;
    int row = params -> row;
    int column = params -> column;
    char textType = params -> textType;
    char fontType = params -> fontType;
    int i;
    int j;
    struct WidgetsAlive* textWindowWidget = NULL;
    GtkWidget *tempTextWidgetPtr;
    GtkTextBuffer *textBuffer;
    gchar* tempLineStr;
    char temp[512];

    GtkTextIter endIter;
    GtkTextIter startIter;
    if(fontType == NORMAL_FONT)
    {
        if(row >15 || row < 0)
            row =15;
        if(column >31 || column < 0)
            column =0;
    }
    // If there is no valid string to write, return
    if ((data == NULL) || (strlen(data) == 0)){
        free(params);
        return FALSE;
    }
    textWindowWidget = getWidgetFromList(1);
    if (textWindowWidget != NULL)
    {
        tempTextWidgetPtr = textWindowWidget->widPtr;
    }
    else
    {
        /* Error */
        free(params);
        return FALSE;
    }
    textBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(tempTextWidgetPtr));
    gtk_text_buffer_get_end_iter (textBuffer, &endIter);
    gtk_text_buffer_get_start_iter (textBuffer, &startIter);
    i = gtk_text_buffer_get_line_count(textBuffer);
    memset(temp, '\0', sizeof(temp));
    if (i < (row+1))
    {
        for (j = i; j < (row + 1); j++)
        {
            strcat(temp, "\n");
        }
        //Move one char forward if you are at the newline char
        while ((gtk_text_iter_get_char(&endIter) != 0))
        {
            gtk_text_iter_forward_char(&endIter);
        }
        gtk_text_buffer_insert(textBuffer,&endIter, temp, -1);
        gtk_text_buffer_get_end_iter (textBuffer, &endIter);
        gtk_text_buffer_get_iter_at_line(textBuffer, &endIter, row);
        memset(temp, '\0', sizeof(temp));
        for (j = 0; j < column+1; j++)
        {
            strcat(temp, " ");
        }
        gtk_text_buffer_insert(textBuffer, &endIter, temp, -1);
    }
    else
    {
        gtk_text_buffer_get_iter_at_line(textBuffer, &startIter, row);
        gtk_text_buffer_get_iter_at_line(textBuffer, &endIter, row);
        gtk_text_view_forward_display_line_end(GTK_TEXT_VIEW(tempTextWidgetPtr), &endIter);
        tempLineStr = gtk_text_buffer_get_text(textBuffer, &startIter, &endIter, FALSE);
        memset(temp, '\0', sizeof(temp));
        i = strlen(tempLineStr);
        if (column > i)
        {
            for (j = 0; j < (column - i); j++)
            {
                strcat(temp, " ");
            }
            gtk_text_buffer_insert(textBuffer,&endIter, temp, -1);
        }
    }
    gtk_text_buffer_get_iter_at_line_offset(textBuffer, &startIter, row, column);
    endIter = startIter;
    i = strlen(data);
    j = 0;
    while (j < i)
    {
        if ((gtk_text_iter_get_char(&endIter) == '\n'))
        {
            gtk_text_iter_backward_char(&endIter);
            break;
        }
        gtk_text_iter_forward_char(&endIter);
        j++;
    }
    if (gtk_text_iter_compare(&endIter, &startIter) == 1) // delete only if enditer is greater than startiter
        gtk_text_buffer_delete( textBuffer, &startIter, &endIter);
    memset(temp, '\0', sizeof(temp));
    j = strlen(data);
    if ( ((j + column) > 32) && (fontType == NORMAL_FONT))
    {
        strncpy(temp, data, (32 - column));
    }
    else
    {
        strncpy(temp, data, j);
    }
    gtk_text_buffer_insert(textBuffer,&startIter, temp, -1);

    gtk_text_buffer_get_end_iter (textBuffer, &endIter);
    gtk_text_buffer_get_start_iter (textBuffer, &startIter);
    if(textType==NORMAL_TEXT)
        gtk_text_buffer_apply_tag_by_name (textBuffer, "bold", &startIter, &endIter);
    else
    {
        gtk_text_buffer_get_iter_at_line_offset(textBuffer, &startIter, row, column);
        gtk_text_buffer_apply_tag_by_name (textBuffer, "Redbold", &startIter, &endIter);
    }
    if((fontType == NORMAL_FONT) || (fontType == NORM_FONT_UNLTD))
    {
        gtk_text_buffer_apply_tag_by_name (textBuffer, "fontSize", &startIter, &endIter);
    }
    else
    {
        gtk_text_buffer_get_iter_at_line_offset(textBuffer, &startIter, row, column);
        gtk_text_buffer_apply_tag_by_name (textBuffer, "smallFontSize", &startIter, &endIter);
    }
    gtk_text_buffer_apply_tag_by_name (textBuffer, "fontweight", &startIter, &endIter);
    gtk_widget_show(tempTextWidgetPtr);
    gtk_widget_show_all(window);
    free(params);
    return FALSE;
}


void updateTextPage(char* data, int row, int column,char textType,char fontType)
{
    updateTextPage_struct *params;
    params = (updateTextPage_struct*)malloc(sizeof(updateTextPage_struct));
    params->data = data;
    params->row = row;
    params->column = column;
    params->textType = textType;
    params->fontType = fontType;
    while(gtk_events_pending())
    {
        usleep(1000);
    }
    waitForLoop=1;
    g_idle_add_full(G_PRIORITY_DEFAULT_IDLE,updateTextPage_callBack,params,destroyNotify);
    while(waitForLoop == 1){
        usleep(1000);
    }
}

void *fsmThread_RunFunction1()
    {

    int atmMsgRetVal;
    static STRUCT_MSG atmRxMsg;
    while(1)
    {
        memset(&atmRxMsg,'\0',sizeof(STRUCT_MSG));
        atmMsgRetVal = PendMessageQ(FSM_CHANNEL,&atmRxMsg);
        if(atmMsgRetVal == 0)
        {

            if(ProcessfsmMessage(atmRxMsg.msgType, (char *)atmRxMsg.msgBuf))
                continue;
        }
        else{
            //sleep(1);
            usleep(10*1000);
        }
    }
    }

int ProcessfsmMessage(int msgType, char *msgBuf)
{
    printf("fsmThread_RunFunction data recieved %s\n",msgBuf);



}

void *fsmThread_RunFunction()
{
    int pollMsgRetVal = -1;
    sleep(5000);
    dispTextPage("icon132.gif",0);
    char data[500] = "FSM POST MESSAGE\n";
    while(1){

        printf("Now Entry for fsmThread_RunFunction\n");
        PostMessageQ(FSM_CHANNEL,1, data,strlen(data));
        dispTextPage("icon165.gif",0);
        sleep(500);
        printf("Now Exit for fsmThread_RunFunction\n");
    }
}

int main(int argc, char *argv[])
{
    GThread *fsmThreadId,*fsmThreadId1;
    GError *error = NULL;
    g_thread_init(NULL);
    //dispInit(argc, argv);

   // sleep(5000);
    CreateMessageQ(FSM_CHANNEL);
    printf("Initializing the display library\n");
    gtk_init(&argc, &argv);
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_resize(GTK_WINDOW(window), 640, 480);
    gtk_window_set_default_size(GTK_WINDOW(window), 640, 480);
    gtk_widget_realize( window );
    gtk_window_set_decorated(GTK_WINDOW(window), FALSE);


    dispInfoPage("icon165.gif",1);
    sleep(5000);
    printf("Now create ethread ");
    fsmThreadId = g_thread_create(fsmThread_RunFunction,NULL,TRUE,&error);
    if (error) {
      fflush(stderr);
      exit(1);
    }
    fsmThreadId1 = g_thread_create(fsmThread_RunFunction1,NULL,TRUE,&error);
    if (error) {
      fflush(stderr);
      exit(1);
    }

    gtk_main();

    g_thread_join(fsmThreadId);
    sleep(2);

    printf("ENd of main");
    return 0;
}


int PostMessageQ(int channel, int msgType, char *msgBuf, int msgSize)
{
    STRUCT_MSG txMsg;
    memset(&txMsg,'\0',sizeof(STRUCT_MSG));
    txMsg.msgType = msgType;
    txMsg.msgSize = msgSize;
    memcpy(&txMsg.msgBuf[0],&msgBuf[0],msgSize);
    g_queue_push_head (msgQueueId[channel], (char *)&txMsg);
    return 0;
}

int PendMessageQ(int channel,STRUCT_MSG* rxMsgptr)
{
    if (g_queue_is_empty(msgQueueId[channel])){
        return 1;
    }
    STRUCT_MSG* rxMsg = (STRUCT_MSG*) malloc(sizeof(STRUCT_MSG));
    rxMsg = ( STRUCT_MSG*) g_queue_pop_tail (msgQueueId[channel]);
    rxMsgptr->msgType = rxMsg->msgType;
    rxMsgptr->msgSize = rxMsg->msgSize;
    memcpy(&rxMsgptr->msgBuf[0],&rxMsg->msgBuf[0],sizeof(rxMsg->msgBuf));
    free(rxMsg);
    return 0;
}


void CreateMessageQ (int channel)
{
  G_LOCK (queue_memchunk);
  msgQueueId[channel] = g_trash_stack_pop (&free_queue_nodes);

  if (!msgQueueId[channel])
    {
      if (!queue_memchunk)
        queue_memchunk = g_mem_chunk_new ("GLib GQueue chunk",
                                          sizeof (GNode),
                                          sizeof (GNode) * 128,
                                          G_ALLOC_ONLY);
      msgQueueId[channel] = g_chunk_new (GQueue, queue_memchunk);
    }
  G_UNLOCK (queue_memchunk);

  msgQueueId[channel]->head = NULL;
  msgQueueId[channel]->tail = NULL;
  msgQueueId[channel]->length = 0;
}

您沒有向我們提供正在使用的GTK的版本,但是這可能是某些較舊的GTK 2發行版中的已知問題。 檢查我對這個問題的答案: https : //stackoverflow.com/a/12950519/518853

訂閱錯誤707760以跟蹤捆綁軟件更新。

  1. 使用了不需要的GQUEUE創建,因此將CreateMessageQ更改如下:

    void CreateMessageQ(整數通道){msgQueueId [channel] = g_queue_new(); }

  2. 問題是PendMessageQ free的更改是:

    int PendMessageQ(int channel,STRUCT_MSG * rxMsgptr){while(g_queue_is_empty(msgQueueId [channel])){g_usleep(10 * 1000); } char data =(data )g_queue_pop_tail(msgQueueId [channel]); memcpy(&rxMsgptr-> msgBuf [0],&data [0],sizeof(data)); 免費(數據); 返回0; }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM