main.c.bak

来自「memprof source code, linux」· BAK 代码 · 共 1,816 行 · 第 1/4 页

BAK
1,816
字号
/* -*- mode: C; c-file-style: "linux" -*- *//* MemProf -- memory profiler and leak detector * Copyright 1999, 2000, 2001, Red Hat, Inc. * Copyright 2002, Kristian Rietveld * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//*====*/#define _GNU_SOURCE#include "config.h"#include <stdarg.h>#include <stdio.h>#include <errno.h>#include <sys/wait.h>#include <signal.h>#include <glade/glade.h>#include <gnome.h>#include <gconf/gconf-client.h>#include <regex.h>#include "leakdetect.h"#include "gui.h"#include "memprof.h"#include "process.h"#include "profile.h"#include "server.h"struct _ProcessWindow {	MPProcess *process;	Profile *profile;	GSList *leaks;	GtkWidget *main_window;	GtkWidget *main_notebook;	GtkWidget *n_allocations_label;	GtkWidget *bytes_per_label;	GtkWidget *total_bytes_label;	GtkWidget *profile_func_clist;	GtkWidget *profile_caller_clist;	GtkWidget *profile_child_clist;	GtkWidget *leak_block_clist;	GtkWidget *leak_stack_clist;	GtkWidget *usage_max_label;	GtkWidget *usage_canvas;	guint usage_max;	guint usage_high;	guint usage_leaked;	GnomeCanvasItem *usage_frame;	GnomeCanvasItem *usage_current_bar;	GnomeCanvasItem *usage_high_bar;	GnomeCanvasItem *usage_leak_bar;	guint status_update_timeout;	gboolean follow_fork : 1;	gboolean follow_exec : 1;};char *glade_file;MPServer *global_server;static ProcessWindow *process_window_new (void);static void process_window_destroy (ProcessWindow *pwin);static void process_window_reset   (ProcessWindow *pwin);static GSList *skip_funcs = NULL;static GSList *skip_regexes = NULL;static gboolean default_follow_fork = FALSE;static gboolean default_follow_exec = FALSE;char *stack_command = NULL;GSList *process_windows = NULL;static GladeXML *pref_dialog_xml = NULL; /* We save this around, so we can prevent multiple property boxes from being opened at once *//************************************************************ * Status Page  ************************************************************/static voidupdate_bars (ProcessWindow *pwin){	gint bytes_used;	if (pwin->process)		bytes_used = pwin->process->bytes_used;	else		bytes_used = 0;		gnome_canvas_item_set (pwin->usage_current_bar,			       "x2", ((double)pwin->usage_canvas->allocation.width *				      (double)bytes_used / pwin->usage_max),			       NULL);	gnome_canvas_item_set (pwin->usage_high_bar,			       "x2", ((double)pwin->usage_canvas->allocation.width *				      (double)pwin->usage_high / pwin->usage_max),			       NULL);	gnome_canvas_item_set (pwin->usage_leak_bar,			       "x2", ((double)pwin->usage_canvas->allocation.width *				      (double)pwin->usage_leaked / pwin->usage_max),			       NULL);	printf("=======max= %ld, use_high = %ld============\n", pwin->usage_max, pwin->usage_high );}static gbooleanupdate_status (gpointer data){	char *tmp;	ProcessWindow *pwin = (ProcessWindow *)data;	tmp = g_strdup_printf ("%d", pwin->process->bytes_used);	gtk_label_set_text (GTK_LABEL (pwin->total_bytes_label), tmp);	g_free (tmp);	tmp = g_strdup_printf ("%d", pwin->process->n_allocations);	gtk_label_set_text (GTK_LABEL (pwin->n_allocations_label), tmp);	g_free (tmp);	if (pwin->process->n_allocations == 0)		tmp = g_strdup("-");	else		tmp = g_strdup_printf ("%.2f",				       (double)pwin->process->bytes_used /					       pwin->process->n_allocations);	gtk_label_set_text (GTK_LABEL (pwin->bytes_per_label), tmp);	g_free (tmp);	if (pwin->process->bytes_used > pwin->usage_max) {		while ((pwin->process->bytes_used > pwin->usage_max))			pwin->usage_max *= 2;			tmp = g_strdup_printf ("%dk", pwin->usage_max / 1024);		gtk_label_set_text (GTK_LABEL (pwin->usage_max_label), tmp);		g_free (tmp);	}	pwin->usage_high = MAX (pwin->process->bytes_used, pwin->usage_high);	update_bars (pwin);		return TRUE;}static voidusage_canvas_size_allocate (GtkWidget     *widget,			    GtkAllocation *allocation,			    ProcessWindow *pwin){	gnome_canvas_set_scroll_region (GNOME_CANVAS (widget),					0, 0,					allocation->width, allocation->height);			gnome_canvas_item_set (pwin->usage_frame,			       "x2", (double)allocation->width - 1,			       "y2", (double)allocation->height - 1,			       NULL);	gnome_canvas_item_set (pwin->usage_current_bar,			       "y2", (double)allocation->height - 1,			       NULL);	gnome_canvas_item_set (pwin->usage_high_bar,			       "y2", (double)allocation->height - 1,			       NULL);	gnome_canvas_item_set (pwin->usage_leak_bar,			       "y2", (double)allocation->height - 1,			       NULL);}					    /************************************************************ * GUI for profiles ************************************************************/static gintprofile_compare_name (GtkCList     *clist,		      gconstpointer ptr1,		      gconstpointer ptr2){	ProfileFunc *func1 = ((const GtkCListRow *)ptr1)->data;	ProfileFunc *func2 = ((const GtkCListRow *)ptr2)->data;	return strcmp (func1->symbol->name, func2->symbol->name);}							     static gintprofile_compare_self (GtkCList     *clist,		      gconstpointer ptr1,		      gconstpointer ptr2){	ProfileFunc *func1 = ((const GtkCListRow *)ptr1)->data;	ProfileFunc *func2 = ((const GtkCListRow *)ptr2)->data;	return func1->self < func2->self ? 1 :		(func1->self > func2->self ? -1 : 0);}							     static gintprofile_compare_total (GtkCList     *clist,		       gconstpointer ptr1,		       gconstpointer ptr2){	ProfileFunc *func1 = ((const GtkCListRow *)ptr1)->data;	ProfileFunc *func2 = ((const GtkCListRow *)ptr2)->data;	return func1->total < func2->total ? 1 :		(func1->total > func2->total ? -1 : 0);}static voidprofile_func_click_column (GtkWidget *clist, gint column){	static const GtkCListCompareFunc compare_funcs[] = {		profile_compare_name,		profile_compare_self,		profile_compare_total	};	g_return_if_fail (column >= 0 && column < 3);	gtk_clist_set_compare_func (GTK_CLIST (clist), compare_funcs[column]);	gtk_clist_sort (GTK_CLIST (clist));}							     static voidprofile_fill_ref_clist (GtkWidget *clist, GList *refs){	gint row;	GList *tmp_list;	gtk_clist_clear (GTK_CLIST (clist));	tmp_list = refs;	while (tmp_list) {		char *data[2];		char buf[32];				ProfileFuncRef *ref = tmp_list->data;		data[0] = ref->function->symbol->name;		g_snprintf(buf, 32, "%d", ref->bytes);		data[1] = buf;		row = gtk_clist_append (GTK_CLIST (clist), data);		gtk_clist_set_row_data (GTK_CLIST (clist), row, ref);		tmp_list = tmp_list->next;	}}static voidprofile_func_select_row (GtkWidget     *widget,			 gint           row,			 gint           column,			 GdkEvent      *event,			 ProcessWindow *pwin){	ProfileFunc *function = gtk_clist_get_row_data (GTK_CLIST (widget), row);	if (function == NULL)		return;	profile_fill_ref_clist (pwin->profile_child_clist, function->children);	profile_fill_ref_clist (pwin->profile_caller_clist, function->inherited);}static gbooleanprofile_ref_button_press (GtkWidget      *widget,			  GdkEventButton *event,			  ProcessWindow  *pwin){	if (event->window == GTK_CLIST (widget)->clist_window &&	    event->type == GDK_2BUTTON_PRESS) {		int my_row, function_row;		if (!gtk_clist_get_selection_info (GTK_CLIST (widget),						   event->x, event->y,						   &my_row, NULL))			return FALSE;		if (my_row != -1) {			ProfileFuncRef *ref;			ref = gtk_clist_get_row_data (GTK_CLIST (widget), my_row);			function_row = gtk_clist_find_row_from_data (GTK_CLIST (pwin->profile_func_clist), ref->function);			if (function_row != -1) {				gtk_clist_select_row (GTK_CLIST (pwin->profile_func_clist), function_row, 0);				gtk_clist_moveto (GTK_CLIST (pwin->profile_func_clist),						  function_row, -1, 0.5, 0.0);			}		}		g_signal_stop_emission_by_name (G_OBJECT (widget), "button_press_event");		return TRUE;	}		return FALSE;}static voidprofile_fill (ProcessWindow *pwin, GtkCList *clist){	int i, row;	gtk_clist_clear (clist);	for (i=0; i<pwin->profile->n_functions; i++) {		ProfileFunc *function = pwin->profile->functions[i];		char *data[3];		char buf[32];				data[0] = function->symbol->name;		g_snprintf(buf, 32, "%u", function->self);		data[1] = g_strdup (buf);		g_snprintf(buf, 32, "%u", function->total);		data[2] = g_strdup (buf);		row = gtk_clist_append (clist, data);		g_free (data[1]);		g_free (data[2]);		gtk_clist_set_row_data (clist, row, function);	}	if (clist->rows > 0)		profile_func_select_row (GTK_WIDGET (clist), 0, 0, NULL, pwin);}/************************************************************ * GUI for leak detection ************************************************************/static voidleak_block_select_row (GtkWidget     *widget,		       gint           row,		       gint           column,		       GdkEvent      *event,		       ProcessWindow *pwin){	Block *block = gtk_clist_get_row_data (GTK_CLIST (widget), row);	StackElement *stack;	if (block == NULL)		return;	gtk_clist_clear (GTK_CLIST (pwin->leak_stack_clist));	for (stack = block->stack; !STACK_ELEMENT_IS_ROOT (stack); stack = stack->parent) {		char *data[3];		char buf[32];		const char *filename;		char *functionname;		unsigned int line;				if (!process_find_line (pwin->process, stack->address,					&filename, &functionname, &line)) {			/* 0x3f == '?' -- suppress trigraph warnings */			functionname = g_strdup ("(\x3f\x3f\x3f)");			filename = "(\x3f\x3f\x3f)";			line = 0;		}				data[0] = functionname;				g_snprintf(buf, 32, "%d", line);		data[1] = buf;				data[2] = (char *)filename;		gtk_clist_append (GTK_CLIST (pwin->leak_stack_clist), data);		free (data[0]);	}		}static voidleaks_fill (ProcessWindow *pwin, GtkCList *clist){	gint row;	GSList *tmp_list;	gtk_clist_clear (clist);	tmp_list = pwin->leaks;	while (tmp_list) {		char *data[3];		char buf[32];		const char *filename;		char *functionname = NULL;		unsigned int line;				Block *block = tmp_list->data;		StackElement *stack;		for (stack = block->stack; !STACK_ELEMENT_IS_ROOT (stack); stack = stack->parent) {			if (process_find_line (pwin->process, stack->address,					       &filename, &functionname, &line)) {				GSList *tmp_list;				if (!functionname)					continue;				for (tmp_list = skip_funcs; tmp_list != NULL; tmp_list = tmp_list->next) {					if (!strcmp (functionname, tmp_list->data)) {						free (functionname);						functionname = NULL;						break;					}				}				if (!functionname)					continue;				for (tmp_list = skip_regexes; tmp_list != NULL; tmp_list = tmp_list->next) {					regex_t regex;					regcomp (&regex, tmp_list->data, 0);					if (!regexec (&regex, functionname, 0, NULL, 0)) {						free (functionname);						functionname = NULL;						regfree (&regex);						break;					}					regfree (&regex);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?