2016-05-25 85 views
0

我得到一个分段错误,由于使用GTK的的g_signal_connect当通过指针的内存地址发生变化。GTK + C:指针地址更改

这是发生在只有我的三台计算机之一。一台不工作的计算机正在运行Arch Linux,因此我认为某些程序的版本比其他两台运行Fedora的计算机都早。我认为它是GTK +,所以我试图降级,这没有任何影响。

奇怪的事情......不管我在哪里编译程序,它始终工作在两台计算机上,并在一个不工作,所以我不认为这有什么做的编译器版本。

头文件:

typedef struct Timer { 
    gboolean running; 
} *TimerP; 

typedef struct TimerData { 
    TimerP timerPointer; 
} *TimerDataP; 

主营:

TimerP timerPointer; 
timerPointer = malloc(sizeof(struct Timer)); 

TimerDataP timerDataP; 
timerDataP = malloc(sizeof(struct TimerData)); 
timerDataP->timerPointer = timerPointer; 

g_signal_connect (startButton, "clicked", G_CALLBACK (startTimerPressed), timerDataP); 

startTimerPressed功能:

static void startTimerPressed (GtkWidget *widget, gpointer data, TimerDataP timerData) { 
    TimerP timer = timerData->timerPointer; 
} 

为了测试,我一直在周期性地这样做,这似乎无处不在工作中主:

gpointer theGPointer; 
startTimerPressed(startButton, theGPointer, timerDataP); 

但由于某些原因,当它使用回调调用,存储位置已经改变,并且所有的数据内部搞砸了,所以试图访问任何导致分段错误。

请&谢谢你的任何援助!

完整的例子:

#include <stdio.h> 
#include <gtk/gtk.h> 
#include <glib.h> 
#include <time.h> 
#include <cairo.h> 
#include <stdlib.h> 

typedef struct Timer { 
    gboolean running; 
}*TimerP; 

typedef struct TimerData { 
    TimerP timerPointer; 
} *TimerDataP; 

static void startTimerPressed (GtkWidget *widget, gpointer data, TimerDataP timerData) { 
    printf("TimerData Location: %p\n", timerData); 
    TimerP timer = timerData->timerPointer; 
} 

int main (int argc, char *argv[]) { 
    GtkWidget *startButton; 
    GtkWidget *window; 
    GtkWidget *grid; 

    gtk_init (&argc, &argv); 

    window = gtk_window_new (GTK_WINDOW_TOPLEVEL); 
    gtk_window_set_default_size(GTK_WINDOW(window), 550, 200); 
    g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL); 
    gtk_container_set_border_width (GTK_CONTAINER (window), 20); 

    grid = gtk_grid_new(); 
    gtk_grid_set_column_spacing(GTK_GRID(grid), 20); 
    gtk_grid_set_row_spacing(GTK_GRID(grid), 10); 
    gtk_container_add (GTK_CONTAINER (window), grid); 

    startButton = gtk_button_new_with_label ("Start"); 

    TimerP timerPointer; 
    timerPointer = malloc(sizeof(struct Timer)); 

    TimerDataP timerDataP; 
    timerDataP = malloc(sizeof(struct TimerData)); 

    printf("TimerData Location: %p\n", timerDataP); 

    g_signal_connect (startButton, "clicked", G_CALLBACK (startTimerPressed), timerDataP); 
    gtk_grid_attach (GTK_GRID (grid), startButton, 0, 4, 1, 1); 

    gtk_widget_show_all(window); 

    gtk_main(); 
} 

在我的两个计算机,打印的存储器位置是在这两个位置是相同的,在其中的一个,它是不同

+0

请尝试创建一个[最小,完整,可验证的示例](http://stackoverflow.com/help/mcve),并告诉我们,现在它不可能做任何事情,但猜测。 –

+0

我的歉意,第一次发布。我已更新该帖子以包含完整示例 –

回答

1
static void startTimerPressed (GtkWidget *widget, gpointer data, TimerDataP timerData) { 

gpointer data参数您传递给g_signal_connect()的数据。您要求的参数多于clicked信号给您的参数。这是一个耻辱有没有办法来检查信号的功能参数:/你要

static void startTimerPressed (GtkWidget *widget, TimerDataP timerData) { 

static void startTimerPressed (GtkWidget *widget, gpointer data) { 
    TimeDataP timerData = (TimerDataP) data; 

代替。

+0

这确实解决了我的问题,现在我的代码正在处理我的所有计算机。谢谢!!!!我仍然很好奇,为什么我的旧代码可以在某些计算机上运行,​​而不是在其他计算机上运行。我试图降级我的GTK版本,这似乎没有任何影响。任何想要改变新版本以防止这些代码工作的想法? –

+0

你的指针可能在某些其他操作的堆栈上。真正发生的事情不能保证;这是未定义行为的魔力。 – andlabs