如何使用太多内存来优化GtkListStore?

时间:2016-12-02 21:59:48

标签: c memory-management out-of-memory gtk3

我正在建立一个离线的闪米特根数据库程序来练习MySQL,并决定将GTK3用于GUI。

我遇到的问题是GtkListStore不断崩溃程序,因为它分配了太多内存。

我发现当我加载Triliteral根时,程序很好但是当我清除liststore并再次加载Triliteral根时,它会分配比所需更多的内存。

无论如何,问题是:我如何正确地释放Liststore?我无数次在网上搜索过,无法找到答案,所以我放弃了,并在这里问。

以下是该计划的代码。

appmain.c

#ifdef __linux__ 
    #include <stdio.h>
    #include <stdlib.h>
    #include <mysql/mysql.h>
    #include <gtk/gtk.h>
    #include <glib.h>
    #include <string.h>

#elif defined(_WIN32) || defined(WIN32) || defined(_WIN64)
    #include <windows.h>
    #include <winsock.h>
#endif

#include "widgets.h"

/*
rootid - INT -> must be primary key = PRIMARY KEY (rootid) NOT NULL AUTO_INCREMENT
rootwords - VARCHAR(4)
rootmeanings - VARCHAR(1024)

create table syriacroots (rootid INT AUTO_INCREMENT NOT NULL, rootwords VARCHAR(4), rootmeanings VARCHAR(1024), PRIMARY KEY (rootid));
*/

int main(int argc, char **argv)
{
    gtk_init(&argc, &argv);

    /* pshaqa is Syriac-Aramaic for solution, create and allocate memory for all the data our app needs */
    struct mainApp *pshaqa = malloc( sizeof(struct mainApp) );
    if (!pshaqa) {
        printf("ERROR: main::pshaqa - **** malloc returned NULL ****\n");
        goto end;
    }

    // start up and assert connection to database.
    /* removed mysql sensitive code */
    /* create the main window */
    pshaqa->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    setup_mainwindow(pshaqa->window);

    /* create page 1 which will handle the roots information and the listboxes */
    GtkWidget *scrolledwindow = gtk_scrolled_window_new(NULL, NULL);
    gtk_container_add(GTK_CONTAINER(pshaqa->window), scrolledwindow);

    /* create notebook-style page control for the program */
    pshaqa->notebook = gtk_notebook_new();
    gtk_container_add(GTK_CONTAINER(scrolledwindow), pshaqa->notebook);

    GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 10);
    GtkWidget *lblRoot = gtk_label_new("Semitic Roots Control");
    gtk_widget_set_tooltip_text(GTK_WIDGET(lblRoot), "Notebook Area that concerns modifying the Syriac Roots database.");

    /* page 2 will handle quit, about, and rebuilding the roots */
    GtkWidget *vbox2 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 1);
    GtkWidget *lblInfo = gtk_label_new("Information");
    gtk_widget_set_tooltip_text(GTK_WIDGET(lblInfo), "Misc. Info Area to Quit the application, About the application, or Rebuild the Syriac roots list.");

    /* add the new pages to the notebook itself */
    gtk_notebook_append_page(GTK_NOTEBOOK(pshaqa->notebook), vbox, lblRoot);
    gtk_notebook_append_page(GTK_NOTEBOOK(pshaqa->notebook), vbox2, lblInfo);

    /* create list store and tree iterator */
    pshaqa->areaRoots.liststore = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
    //GtkTreeIter treeiter;

    /* set up initial liststore info */
    //gtk_list_store_append(pshaqa->areaRoots.liststore, &treeiter);
    //gtk_list_store_set(pshaqa->areaRoots.liststore, &treeiter, 0, "click on roots button to set the list", 1, "", -1);

    /* setup our tree view and add it to the window */
    GtkWidget *treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(pshaqa->areaRoots.liststore));

    /* setup the cell renderer so we can hold our text then setup the columns on the treeview */
    /*GtkCellRenderer *cellrendNum = gtk_cell_renderer_text_new();
    pshaqa->areaRoots.treeviewcolumn = gtk_tree_view_column_new_with_attributes("Root ID", cellrendNum, "text", 0, NULL);
    g_object_set(cellrendNum, "editable", TRUE, NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), pshaqa->areaRoots.treeviewcolumn);
    g_signal_connect(cellrendNum, "edited", G_CALLBACK(on_idcell_edited), pshaqa->areaRoots.liststore);*/

    /* create and setup the Root string column */
    GtkCellRenderer *cellrendRoot = gtk_cell_renderer_text_new();
    pshaqa->areaRoots.treeviewcolumn = gtk_tree_view_column_new_with_attributes("Literal Root", cellrendRoot, "text", 0, NULL);
    //g_object_set(cellrendRoot, "editable", TRUE, NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), pshaqa->areaRoots.treeviewcolumn);
    //g_signal_connect(cellrendRoot, "edited", G_CALLBACK(on_rootcell_edited), pshaqa->areaRoots.liststore);
    //g_signal_connect(treeview, "row-deleted", G_CALLBACK(on_row_deleted), pshaqa->areaRoots.liststore);

    /* create and setup the Root meaning column */
    //GtkCellRenderer *cellrendMeaning = gtk_cell_renderer_text_new();
    pshaqa->areaRoots.treeviewcolumn = gtk_tree_view_column_new_with_attributes("Meaning", cellrendRoot, "text", 1, NULL);
    g_object_set(cellrendRoot, "editable", TRUE, NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), pshaqa->areaRoots.treeviewcolumn);
    g_signal_connect(cellrendRoot, "edited", G_CALLBACK(on_meaningcell_edited), pshaqa->areaRoots.liststore);

    /* make Biliteral Roots button */
    pshaqa->areaRoots.btnBi = gtk_button_new_with_label("Biliteral Roots");

    /* TODO: make void* array and pass the root struct along with liststore */
    g_signal_connect(GTK_BUTTON(pshaqa->areaRoots.btnBi), "clicked", G_CALLBACK(biroots_clicked), pshaqa->areaRoots.liststore);
    gtk_box_pack_start(GTK_BOX(vbox), pshaqa->areaRoots.btnBi, TRUE, TRUE, 0);
    gtk_widget_set_tooltip_text(GTK_WIDGET(pshaqa->areaRoots.btnBi), "Button that loads the Biliteral Syriac Roots");

    /* make Trilieral roots button */
    pshaqa->areaRoots.btnTri = gtk_button_new_with_label("Triliteral Roots");
    g_signal_connect(GTK_BUTTON(pshaqa->areaRoots.btnTri), "clicked", G_CALLBACK(triroots_clicked), pshaqa->areaRoots.liststore);
    gtk_box_pack_start(GTK_BOX(vbox), pshaqa->areaRoots.btnTri, TRUE, TRUE, 0);
    gtk_widget_set_tooltip_text(GTK_WIDGET(pshaqa->areaRoots.btnTri), "Button that loads the Triliteral Syriac Roots");

    /* make Quadliteral roots button */
    pshaqa->areaRoots.btnQuad = gtk_button_new_with_label("Quadliteral Roots");
    g_signal_connect(GTK_BUTTON(pshaqa->areaRoots.btnQuad), "clicked", G_CALLBACK(quadroots_clicked), pshaqa->areaRoots.liststore);
    gtk_box_pack_start(GTK_BOX(vbox), pshaqa->areaRoots.btnQuad, TRUE, TRUE, 0);
    gtk_widget_set_tooltip_text(GTK_WIDGET(pshaqa->areaRoots.btnQuad), "Button that loads the Quadliteral Syriac Roots");

    gtk_box_pack_start(GTK_BOX(vbox), treeview, TRUE, TRUE, 0);

    gtk_widget_show_all(pshaqa->window);
    gtk_main();

    if (pshaqa)
        free(pshaqa);
    pshaqa = NULL;
end:
    return 0;
}

void window_destroy(GtkWidget *widget, gpointer data)
{
    gtk_main_quit();
}

void biroots_clicked(GtkWidget *btn, gpointer data)
{
    GtkTreeIter treeiter;
    /* clear the entire listing to update for new list */
    gtk_list_store_clear(GTK_LIST_STORE(data));

    const char *atwate[] = {"ܐ","ܒ","ܓ","ܕ","ܗ","ܘ","ܙ","ܚ","ܛ","ܝ","ܟ","ܠ","ܡ","ܢ","ܣ","ܥ","ܦ","ܨ","ܩ","ܪ","ܫ","ܬ"};
    const unsigned char nloop = sizeof( atwate ) / sizeof( *atwate );

    gchar roots[5];
    unsigned char i, j;
    for (i=0; i < nloop; i++) {
        for (j=0; j < nloop; j++) {
            sprintf(roots, "%s%s", atwate[i], atwate[j]);
            gtk_list_store_append(GTK_LIST_STORE(data), &treeiter);
            gtk_list_store_set(GTK_LIST_STORE(data), &treeiter, 0, roots, 1, "", -1);
        }
    }
}
void triroots_clicked(GtkWidget *btn, gpointer data)
{
    GtkTreeIter treeiter;

    /* clear the entire listing to update for new list */
    gtk_list_store_clear(GTK_LIST_STORE(data));

    const char *atwate[] = {"ܐ","ܒ","ܓ","ܕ","ܗ","ܘ","ܙ","ܚ","ܛ","ܝ","ܟ","ܠ","ܡ","ܢ","ܣ","ܥ","ܦ","ܨ","ܩ","ܪ","ܫ","ܬ"};
    const unsigned char nloop = sizeof( atwate ) / sizeof( *atwate );

    gchar roots[7];
    unsigned char i, j, n;
    for (i=0 ; i<nloop ; i++) {
        for (j=0 ; j<nloop ; j++) {
            for (n=0 ; n<nloop ; n++) {
                sprintf(roots, "%s%s%s", atwate[i], atwate[j], atwate[n]);
                gtk_list_store_append(GTK_LIST_STORE(data), &treeiter);
                gtk_list_store_set(GTK_LIST_STORE(data), &treeiter, 0, roots, 1, "", -1);
            }
        }
    }
}
void quadroots_clicked(GtkWidget *btn, gpointer data)
{
    GtkTreeIter treeiter;
    /* clear the entire listing to update for new list */
    gtk_list_store_clear(GTK_LIST_STORE(data));

    const char *atwate[] = {"ܐ","ܒ","ܓ","ܕ","ܗ","ܘ","ܙ","ܚ","ܛ","ܝ","ܟ","ܠ","ܡ","ܢ","ܣ","ܥ","ܦ","ܨ","ܩ","ܪ","ܫ","ܬ"};
    const unsigned char nloop = sizeof( atwate ) / sizeof( *atwate );

    gchar roots[9];
    unsigned char i, j, n, t;
    for (i=0 ; i<nloop ; i++) {
        for (j=0 ; j<nloop ; j++) {
            for (n=0 ; n<nloop ; n++) {
                for (t=0 ; t<nloop ; t++) {
                    sprintf(roots, "%s%s%s%s", atwate[i], atwate[j], atwate[n], atwate[t]);
                    gtk_list_store_append(GTK_LIST_STORE(data), &treeiter);
                    gtk_list_store_set(GTK_LIST_STORE(data), &treeiter, 0, roots, 1, "", -1);
                }
            }
        }
    }
}

void on_meaningcell_edited(GtkWidget *cellrenderer, gchar *path, gchar *text, gpointer data)
{
    GtkTreeModel *model = (GtkTreeModel *)data;
    GtkTreePath *treepath = gtk_tree_path_new_from_string(path);
    GtkTreeIter treeiter;

    gtk_tree_model_get_iter(model, &treeiter, treepath);

    gtk_list_store_set(GTK_LIST_STORE(model), &treeiter, 1, text, -1);
}

void on_row_deleted(GtkTreeModel *tree_model, GtkTreePath *path, gpointer user_data)
{
    if (path)
        gtk_tree_path_free(path);
    path = NULL;
}

void setup_mainwindow(GtkWidget *x)
{
    gtk_window_set_default_size(GTK_WINDOW(x), 800, 300);
    gtk_window_set_title(GTK_WINDOW(x), "Syriac Database Program");
    g_signal_connect(x, "destroy", G_CALLBACK(window_destroy), NULL);
}

widgets.h

#ifndef WIDGETSZ
    #define WIDGETSZ

#ifdef __linux__
    #include <gtk/gtk.h>

#elif defined(_WIN32) || defined(WIN32) || defined(_WIN64)
    #include <windows.h>
    #include <winsock.h>
#endif

struct root {
    unsigned int iID;
    char strRoot[5];        // size in database = 4
    char *strMeaning;       // size in database = 1024
};

struct page1 {
    GtkWidget
        *btnBi,
        *btnTri,
        *btnQuad
    ;
    GtkListStore        *liststore;
    GtkTreeViewColumn   *treeviewcolumn;
};

struct page2 {
    GtkWidget *btnQuit, *btnAbout, *btnRebuild;
};

struct mainApp {
    GtkWidget
        *aboutdialog,
        *window,
        *treeview,
        *notebook
    ;
    struct page1    areaRoots;
    struct page2    areaInfo;
};


/* callback funcs */
void window_destroy(GtkWidget*, gpointer);
void biroots_clicked(GtkWidget*, gpointer);
void triroots_clicked(GtkWidget*, gpointer);
void quadroots_clicked(GtkWidget*, gpointer);
//void on_idcell_edited(GtkWidget*, gchar*, gchar*, gpointer);
//void on_rootcell_edited(GtkWidget*, gchar*, gchar*, gpointer);
void on_meaningcell_edited(GtkWidget*, gchar*, gchar*, gpointer);
void on_row_deleted(GtkTreeModel*, GtkTreePath*, gpointer);


/* Widget setup funcs */
void setup_mainwindow(GtkWidget*);

#endif /* WIDGETSZ */

0 个答案:

没有答案