【发布时间】:2017-02-08 16:22:24
【问题描述】:
我编写了一个简单的程序模块来询问用户的个人资料名称。为此,我创建了带有条目小部件的 windoww,并在网格中组织了两个按钮(确定和取消)。当用户输入一个已经存在的配置文件名称时,它会通过创建带有“确定”按钮的对话框来通知他这一事实,并且在他按下它之后,它会返回选择配置文件名称(同时窗口没有隐藏也没有破坏) .问题是,当我创建一个配置文件,然后在配置文件名称选择器和对话框(通过创建和销毁对话框创建一个简单的循环) 程序的内存使用量增加。
TL;DR 简单地创建和销毁 gtk 窗口(和对话框)似乎会导致内存泄漏。让应用程序处于循环状态使其内存使用量增加了约 1900%(从 10mb 到 200mb)。
不,我没有使用专为它设计的应用程序测试内存泄漏。 是的,我设置了 G_SLICE=always-malloc。 是的,在程序的后台运行了另一个线程(但我确信它不会导致任何泄漏) 如果您想了解有关内存中发生的情况的更多信息,我可以从 Windows 性能监视器发布屏幕。
问题是 - 是我造成的内存泄漏,还是 GTK 的错(我听说它有一个惰性的内存管理策略,但一段时间后内存使用量从 200mb 下降到 140mb 并保持在那里)?
代码如下:
// This callback racts to the ok and cancel buttons. If input was correcs
// or the user pressed cancel it destroys the window. Else it show error
// prompt. The showing error prompt seems to be the problem here.
void pickNameButtCB(GtkWidget *button, gpointer *call)
{
GtkWidget *window = gtk_widget_get_toplevel(button);
if( *((char*)call) == 'k')
{
GList *entryBase = gtk_container_get_children(GTK_CONTAINER(gtk_bin_get_child(GTK_BIN(window)))), *entry = entryBase;
for(size_t i=g_list_length(entry); i>0 && !GTK_IS_ENTRY(entry->data); --i)
entry = g_list_next(entry);
if(gtk_entry_get_text_length(GTK_ENTRY(entry->data)) > 0)
{
const char *temp = gtk_entry_get_text(GTK_ENTRY(entry->data));
char path[266];
strcpy(path, settingsDir);
strcat(path, temp);
strcat(path, ".prof");
if(settProfExists(path))
{
g_list_free(entryBase);
showError(GTK_WINDOW(window), GTK_MESSAGE_ERROR, "Profile with that name already exists!");
return;
}
// nothing here executes as well
}
else
{
/** doesn't execute when the memory leak happens */
}
g_list_free(entryBase);
}
gtk_widget_destroy(window);
gtk_main_quit();
}
void showError(GtkWindow *parent, GtkMessageType type, const char *str)
{
GtkWidget *window = gtk_message_dialog_new(parent, GTK_DIALOG_DESTROY_WITH_PARENT, type, GTK_BUTTONS_OK, str);
g_signal_connect_swapped(window, "response", G_CALLBACK(gtk_widget_destroy), window);
gtk_dialog_run(GTK_DIALOG(window));
}
bool settProfExists(const char *path)
{
if(fileExists(path))
return true;
return false;
}
bool fileExists(const char *path)
{
struct stat info;
errno = 0;
if((stat(path, &info)) != 0)
if(errno == ENOENT)
return false;
return true;
}
【问题讨论】:
-
“为我调试代码”不是一个好问题。首先从代码中消除多余的细节,直到达到minimal reproducible example。您可能会在此过程中自己发现问题。
-
我看到了你创建窗口的函数,但我没有看到任何窗口的实际创建或销毁。
-
@JohnBollinger “chooseProfName”在这里只是为了完整性。它确实创建了在循环中不断打开的窗口。循环实际上是在 pickNameButtCB 中,运行 showError,对话框在此创建和销毁(我将“响应”信号连接到小部件销毁函数)。
-
如果在消除混乱的同时找不到问题,请发布问题。但我怀疑你迄今为止缺乏成功很大程度上受到细节数量的影响。
-
这不是您上次编辑中的minimal reproducible example。说真的,花时间减少它(即删除代码)而不是不耐烦。
标签: c windows memory-leaks gtk gtk3