GTK - 禁用输入字段时出现 pango 严重错误

GTK - pango-critical error when disabling entry field

我在尝试禁用输入字段时遇到以下错误(两次):

(SDS-CW:7145): Pango-CRITICAL **: 16:38:37.521: pango_layout_get_cursor_pos: assertion 'index >= 0 && index <= layout->length' failed

(SDS-CW:7145): Pango-CRITICAL **: 16:38:37.521: pango_layout_get_cursor_pos: assertion 'index >= 0 && index <= layout->length' failed

这个想法是从输入字段中获取一个 IP 地址到程序中。然而,在我开始尝试验证该条目是一个有效的 IP 地址之前,这一切都运行良好。它曾经在按下提交按钮后立即禁用该字段以防止用户更改输入的文本,但是现在该字段空白并且似乎中断了,如下所示。

当输入字段未被禁用时,我没有收到错误。

但是,验证函数似乎 运行 正常,并且检查函数 wait_for_connction()(在新线程中 运行)开始 运行ning,但始终如一函数迭代 1 次后,将抛出 pango 错误。

这是我在输入字段中输入 192.168.0.254 时的完整控制台输出:

/home/csc/CLionProjects/SDS-CW/GUIs/Server/cmake-build-debug/SDS-CW
Valid IP
Selected Server IP: xxx.xxx.xxx.xxx
Checking server...

(SDS-CW:7423): Pango-CRITICAL **: 16:57:11.582: pango_layout_get_cursor_pos: assertion 'index >= 0 && index <= layout->length' failed

(SDS-CW:7423): Pango-CRITICAL **: 16:57:11.582: pango_layout_get_cursor_pos: assertion 'index >= 0 && index <= layout->length' failed
Checking server...
Checking server...
Checking server...
Checking server...
Connected to: xxx.xxx.xxx.xxx
Conn success

有趣的是,每次 GTK window 失去焦点时,我似乎都会再次遇到错误,然后在重新获得焦点时再次出现错误。

这是按钮的回调:

int connect_server(GtkButton *button, gpointer user_data) {

    struct data *server_data = (struct data*)user_data;

    GtkWidget *serverIPEntry = server_data->serverIPEntry;
    GtkWidget *sererPortEntry = server_data->serverPortEntry;
    GtkWidget *connectButton = server_data->connectButton;
    GtkWidget *serverIPErrorLabel = server_data->serverIPErrorLabel;
    GtkWidget *serverPortErrorLabel = server_data->serverPortErrorLabel;

    char* serverIP = (char*)gtk_entry_get_text(GTK_ENTRY(serverIPEntry));
    char* serverPortStr = (char*)gtk_entry_get_text(GTK_ENTRY(sererPortEntry));

    int serverPort = atoi(serverPortStr);

    int status;

    gtk_widget_set_name(serverIPEntry, "fieldsNormal");
    gtk_label_set_text(GTK_LABEL(serverIPErrorLabel), "");

    // TODO: Check for valid IP and Port

    if (strcmp(serverIP, "") == 0) {

        gtk_widget_set_name(serverIPEntry, "fieldsError");
        gtk_label_set_text(GTK_LABEL(serverIPErrorLabel), "Please enter an IP");

        return -1;
    } else if (validate_ip(serverIP) == 1){
        // TODO: Check if IP Address given is valid
        g_print("Valid IP\n");
    } else {
        g_print("Invalid IP\n");
    }

    g_print("Selected Server IP: %s\n", selectedServerStr);
    gtk_widget_set_sensitive(connectButton, FALSE);
    append_to_log("Attempting connection, please wait...\n", 1);
    gtk_widget_set_sensitive(serverIPEntry, FALSE); // ERROR HAPPENING WHEN I RUN THIS LINE

    gtk_progress_bar_set_text(GTK_PROGRESS_BAR(workingSetProgressBar), "Connecting...");
    status = pthread_create(&connThread, NULL, wait_for_connection, server_data);

    // TODO: Check thread status code
    if (status != 0) {
        printf("Thread returned error code %d\n", status);
        exit(-1);
    }

    return 1;
}

void *wait_for_connection(void* server_data) {

    struct data *srvDat = server_data;
    GtkWidget *disconnectButton = srvDat->disconnectButton;
    GtkWidget *connectButton = srvDat->connectButton;
    GtkWidget *statLabel = srvDat->statLabel;
    GtkWidget *serverIPEntry = srvDat->serverIPEntry;

    requestConnect = 1;

    for (int i = 0; i < 10; i++) {
        gtk_progress_bar_pulse(GTK_PROGRESS_BAR(workingSetProgressBar));
        g_print("Checking server...\n");

        // THIS BELOW IS FOR TESTING ONLY
        if (i == 4) {
            connected = 1;
        }
        // THIS ABOVE IS FOR TESTING ONLY

        if (connected == 1) {
            connSuccess = 1;
            break;
        }
        connSuccess = 0;
        sleep(1);
    }

    if (connSuccess == 1) {
        g_print("Connected to: %s\n", selectedServerStr);
        printf("Conn success\n");
        // TODO: Change button to disconnect button
        // TODO: Set progress to 0

        gtk_widget_hide(connectButton);
        gtk_widget_show(disconnectButton);

        gtk_widget_set_name(statLabel, "connLabel");
        gtk_label_set_text(GTK_LABEL(statLabel), "Connected");

        gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(workingSetProgressBar), 0);
        gtk_progress_bar_set_text(GTK_PROGRESS_BAR(workingSetProgressBar), NULL);

        char* connLog = "Connected To: ";

        char* strToLog;

        if((strToLog = malloc(strlen(connLog)+strlen(selectedServerStr)+5)) != NULL){
            strToLog[0] = '[=12=]';
            strcat(strToLog, connLog);
            strcat(strToLog, selectedServerStr);
            strcat(strToLog, "\n");
        } else {
            // TODO: Deal with failed malloc
        }

        append_to_log(strToLog, 1);
        pthread_exit(&connThread);

    } else if (connSuccess == 0) {
        gtk_widget_set_sensitive(serverIPEntry, TRUE);
        gtk_widget_set_sensitive(connectButton, TRUE);
        printf("Conn failed\n");
        append_to_log("Connection failed\n", 1);
        gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(workingSetProgressBar), 0);
        gtk_progress_bar_set_text(GTK_PROGRESS_BAR(workingSetProgressBar), "Disconnected");
        pthread_exit(&connThread);
    }
}

这是我用来将条目验证为 IP 地址的函数 validate_ip(),这似乎导致了这个问题:

int validate_number(char *str) {
    while (*str) {
        if(!isdigit(*str)){ //if the character is not a number, return false
            return 0;
        }
        str++; //point to next character
    }
    return 1;
}

int validate_ip(char *ip) { //check whether the IP is valid or not
    int i, num, dots = 0;
    char *ptr;
    if (ip == NULL)
        return 0;
    ptr = strtok((char*)ip, "."); //cut the string using dot delimiter
    if (ptr == NULL)
        return 0;
    while (ptr) {
        if (!validate_number(ptr)) //check whether the sub string is holding only number or not
            return 0;
        num = atoi(ptr); //convert substring to number
        if (num >= 0 && num <= 255) {
            ptr = strtok(NULL, "."); //cut the next part of the string
            if (ptr != NULL)
                dots++; //increase the dot count
        } else
            return 0;
    }
    if (dots != 3) //if the number of dots are not 3, return false
        return 0;
    return 1;
}

如有任何帮助,我们将不胜感激。谢谢!

刚刚通过将 validate_ip() 函数的开始更改为如下内容来解决此问题:

int validate_ip(char *ipOrig) { //check whether the IP is valid or not
    char* ip[17];
    strcpy((char*)ip, ipOrig);
    int i, num, dots = 0;
    char *ptr;
....

看起来 validate_ip() 函数更改传递给它的变量的值是一个问题,所以我复制了要在函数中使用的传入变量。