Reputation: 198
I am getting a segmentation fault, due to a passed pointer's memory address changing when using GTK's g_signal_connect.
This is happening on only one of my three computers. The one computer where it is not working, it is running Arch Linux, so I am assuming that some program's version is ahead of my other computers which are both running Fedora. I assumed it was GTK+, so I tried downgrading, and this did not have any affect.
Weird thing... no matter where I compile the program, it always works on the two computers, and does not work on the one, so I don't believe it has anything to do with the compiler version.
Header File:
typedef struct Timer {
gboolean running;
} *TimerP;
typedef struct TimerData {
TimerP timerPointer;
} *TimerDataP;
Main:
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 function:
static void startTimerPressed (GtkWidget *widget, gpointer data, TimerDataP timerData) {
TimerP timer = timerData->timerPointer;
}
To test, I have been doing this periodically, and this seems to work everywhere in main:
gpointer theGPointer;
startTimerPressed(startButton, theGPointer, timerDataP);
But for some reason, when it's called using the callback, the memory location has changed and all the data inside is messed up, so trying to access anything causes a segmentation fault.
Please & thank you for any assistance!
Complete Example:
#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 ();
}
On two of my computers, the memory location printed is the same in both locations, in one of them, it is different
Upvotes: 0
Views: 186
Reputation: 11588
static void startTimerPressed (GtkWidget *widget, gpointer data, TimerDataP timerData) {
The gpointer data
parameter is the data you pass to g_signal_connect()
. You're asking for more parameters than the clicked
signal gives you. It's a shame there's no way to check signal function parameters :/ You want
static void startTimerPressed (GtkWidget *widget, TimerDataP timerData) {
or
static void startTimerPressed (GtkWidget *widget, gpointer data) {
TimeDataP timerData = (TimerDataP) data;
instead.
Upvotes: 1