Я написал простой программный модуль, чтобы спросить у пользователя имя профиля. Для этого я создаю windoww с виджем ввода и двумя кнопками (Ok и Cancel), организованными в сетке. Когда пользователь вводит имя профиля, которое уже существует, он информирует его об этом факте, создавая диалог с кнопкой «ok», и после того, как он нажимает его, он возвращается к выбору имени профиля (окно не было скрыто и не было уничтожено тем временем) , Проблема заключается в том, что когда я создаю профиль, а затем спам кнопки ok (помещая что-то тяжелое на ключ ввода и собираюсь делать чай) как на выбор имени профиля, так и на диалог (создавая простой цикл с созданием и уничтожением диалога) использование памяти программы увеличивается.Цикл создания и уничтожения диалогов увеличивает использование памяти
TL; DR Просто создания и кажется, уничтожив окно GTK (и диалога), чтобы вызвать утечку памяти. Оставляя приложение в цикле, он увеличил использование памяти на ~ 1900% (от 10 до 200 мб).
Нет, я не тестировал утечки памяти с помощью приложений, предназначенных для этого. Да, я установил G_SLICE = always-malloc. Да, в фоновом режиме программы есть другой поток (но я уверен, что он не вызывает никаких утечек) Я могу опубликовать экраны из Windows Performance Monitor, если вы хотите узнать больше о том, что происходит в памяти.
Вопрос - это утечка памяти, вызванная мною, или это ошибка GTK (я слышал, что у нее ленивая политика управления памятью, но через некоторое время использование памяти падает с 200 до 140 мб и остается там)?
Вот код:
// 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;
}
«Отладка мой код для меня» не хороший вопрос. Начните с устранения лишних деталей из вашего кода, пока не достигнете [mcve]. Вы можете найти проблему самостоятельно по пути. – StoryTeller
Я вижу вашу функцию для создания окна, но я не вижу никакого фактического создания или уничтожения каких-либо окон. –
@JohnBollinger «chooseProfName» здесь только для полноты. Он создает окно, которое постоянно открыто в цикле. Цикл действителен в pickNameButtCB, запускает showError, где диалог создается и уничтожается (я подключил сигнал «ответ» к функции уничтожения виджета). – Grabusz