如何在glib :: timer :: stop()上解决此segfault?

发布于 2025-01-31 07:35:06 字数 22475 浏览 2 评论 0原文

bellow is the code according to execution flow and some gdb output, the most relevant functions are start_timer, stop_timer and timeout_timer from Time_Keeper and UI_Controller

u-i-controller.h

#ifndef _U_I_CONTROLLER_H_
#define _U_I_CONTROLLER_H_

#include <unistd.h>
#include <gtkmm.h>
#include <unordered_map>
#include <glibmm/datetime.h>
#include <time-keeper.h>


namespace std{
    template <>
    struct hash<Time_Keeper>
    {
        size_t operator()( Time_Keeper& t) const
        {
            return t.hasheable().hash();
        }
    };
}

class UI_Controller
{
public:
    UI_Controller(Gtk::Builder* refference,Gtk::Application * app);
    void deffine_application(Gtk::Application * app);
    void add_window_to_application(Gtk::Window * window);
protected:

private:
    Gtk::Builder * refference;
    Gtk::ApplicationWindow * content_relations;
    Gtk::Application * app;
    std::vector<Glib::RefPtr<Glib::Object>> widgets;
    std::unordered_map<int,Time_Keeper> bind_time;
    void show_window(Gtk::Window *window);
    void start_timer(Gtk::Widget * selected, int position);
    void stop_timer(int i) { (bind_time[i]).stop_timer (); };
    void restart_timer(int i) { return ;}; // to be done
    void add_timer(int i) { return ;}; //to be done
    bool timeout_timer(Gtk::Label * display,int position);
};

#endif // _U_I_CONTROLLER_H_

u-i-controller.cc

#include "u-i-controller.h"

UI_Controller::UI_Controller(Gtk::Builder * refference, Gtk::Application * app)
{
    deffine_application (app);
    this->refference = refference;
    refference->get_widget("main_window",this->content_relations);
    widgets = refference->get_objects();
    Glib::ustring widget_names = "";
    for (int i=0; i < widgets.size(); i++){
        widget_names = widget_names+dynamic_cast<Gtk::Widget*>(widgets.at(i).get())->get_name()+"\n";
        if (dynamic_cast<Gtk::Buildable*>(widgets.at(i).get())->get_name() == (Glib::ustring) "start_timer"){
            //dynamic_cast<Gtk::Widget*>(widgets.at(i).get())->get_ancestor(GTK_TYPE_BOX)
            //dynamic_cast<Gtk::Button*>(widgets.at(i).get())->signal_clicked().connect(sigc::mem_fun(*this,&Controlador_UI::botao_acionado));
            dynamic_cast<Gtk::Button*>(widgets.at(i).get())->signal_clicked().connect(sigc::bind<Gtk::Widget*>(sigc::mem_fun(*this,&UI_Controller::start_timer),dynamic_cast<Gtk::Widget*>(widgets.at(i).get()),i ) );
        }
        if (dynamic_cast<Gtk::Buildable*>(widgets.at(i).get())->get_name() == (Glib::ustring) "stop_timer"){
            dynamic_cast<Gtk::Button*>(widgets.at(i).get())->signal_clicked().connect(sigc::bind(sigc::mem_fun(*this,&UI_Controller::stop_timer),i ) );
        }
        if (dynamic_cast<Gtk::Buildable*>(widgets.at(i).get())->get_name() == (Glib::ustring) "restart_timer"){
            dynamic_cast<Gtk::Button*>(widgets.at(i).get())->signal_clicked().connect(sigc::bind(sigc::mem_fun(*this,&UI_Controller::restart_timer),i ) );
        }
        if (dynamic_cast<Gtk::Buildable*>(widgets.at(i).get())->get_name() == (Glib::ustring) "add_timer"){
            dynamic_cast<Gtk::Button*>(widgets.at(i).get())->signal_clicked().connect(sigc::bind(sigc::mem_fun(*this,&UI_Controller::add_timer),i ) );
        }
    }
    app->run();
}

void UI_Controller::deffine_application(Gtk::Application * app)
{
    this->app = app;
}

void UI_Controller::add_window_to_application (Gtk::Window * window)
{
    app->add_window(*window);
}

void UI_Controller::show_window(Gtk::Window * window)
{
    add_window_to_application(window);
    window->show();
    window->show_all_children();
}

void UI_Controller::start_timer(Gtk::Widget * selected, int position){
    if (bind_time.find(position) == bind_time.end() ){
        bind_time [position] = *(new Time_Keeper());
        (bind_time [position]).start_timer ();
    }
    Gtk::Label * display;
    refference->get_widget("timer_display",display);

    // both 2 variables bellow yet to be managed by this class

    sigc::slot<bool()> my_slot = sigc::bind(sigc::mem_fun(*this,
              &UI_Controller::timeout_timer), display, position);
    auto conn = Glib::signal_timeout().connect(my_slot, 100);
}

bool UI_Controller::timeout_timer(Gtk::Label * display,int position){
    if ( ((bind_time [position]).get_active()) ) display->set_text((bind_time [position]).display_timer ());
    return (bind_time [position]).get_active();
}

reduced Time_Keeper class

#ifndef _TIME_KEEPER_H_
#define _TIME_KEEPER_H_

#include <glibmm/datetime.h>
#include<memory>
#include <glibmm/timer.h>

class Time_Keeper
{
public:
    void start_timer();
    void stop_timer();
    // I would rather use the constructor, but I need a default one in order \
    to use the unordered list
    Glib::DateTime hasheable() { return Glib::DateTime::create_now_local(); }
    bool get_active() { return active; };
protected:

private:
    std::shared_ptr<Glib::Timer> timer;
    bool active = false;
};

#endif // _TIME_KEEPER_H_
#include "time-keeper.h"

void Time_Keeper::start_timer(){
    active = true;
    timer = std::shared_ptr<Glib::Timer>(new Glib::Timer);
    timer.get()->start(); 
};

void Time_Keeper::stop_timer(){
    active = false;
    timer.get()->stop();
}

main

#include <gtkmm.h>
#include <iostream>

#include "config.h"


#ifdef ENABLE_NLS
#  include <libintl.h>
#endif

#include "u-i-controller.h"

/* For testing propose use the local (not installed) ui file */
/* #define UI_FILE PACKAGE_DATA_DIR"/ui/time_keeper.ui" */
#define UI_FILE "src/time_keeper.ui"

Gtk::ApplicationWindow * main_win = 0;

void activate_app(Gtk::Application * app)
{
    app->add_window(*main_win);
    main_win->show();
    main_win->show_all_children ();
}

int
main (int argc, char *argv[])
{
    
    auto app = Gtk::Application::create(argc,argv,"org.gtkmm.time_keeper");

    //Load the Glade file and instiate its widgets:
    Glib::RefPtr<Gtk::Builder> builder;
    try
    {
        builder = Gtk::Builder::create_from_file(UI_FILE);
    }
    catch (const Glib::FileError & ex)
    {
        std::cerr << ex.what() << std::endl;
        return 1;
    }
    
    builder->get_widget("main_window", main_win);

    if (main_win)
    {
        app->signal_startup().connect(sigc::bind<Gtk::Application*>(sigc::ptr_fun(&activate_app), app.get() ) );
        UI_Controller * controller = new UI_Controller(builder.get(),app.get());
    }
}

time_keeper.ui

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.38.2 -->
<interface>
  <requires lib="gtk+" version="3.24"/>
  <object class="GtkApplicationWindow" id="main_window">
    <property name="can-focus">False</property>
    <child>
      <object class="GtkBox">
        <property name="visible">True</property>
        <property name="can-focus">False</property>
        <property name="orientation">vertical</property>
        <property name="spacing">13</property>
        <property name="homogeneous">True</property>
        <child>
          <object class="GtkBox">
            <property name="visible">True</property>
            <property name="can-focus">False</property>
            <property name="orientation">vertical</property>
            <child>
              <object class="GtkLabel">
                <property name="visible">True</property>
                <property name="can-focus">False</property>
                <property name="label" translatable="yes">current activity time</property>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkScrolledWindow">
                <property name="visible">True</property>
                <property name="can-focus">True</property>
                <property name="shadow-type">in</property>
                <child>
                  <object class="GtkViewport">
                    <property name="visible">True</property>
                    <property name="can-focus">False</property>
                    <child>
                      <!-- n-columns=4 n-rows=3 -->
                      <object class="GtkGrid" id="timer_grid">
                        <property name="visible">True</property>
                        <property name="can-focus">False</property>
                        <child>
                          <object class="GtkEntry">
                            <property name="visible">True</property>
                            <property name="can-focus">True</property>
                            <property name="hexpand">True</property>
                          </object>
                          <packing>
                            <property name="left-attach">0</property>
                            <property name="top-attach">0</property>
                            <property name="width">3</property>
                          </packing>
                        </child>
                        <child>
                          <object class="GtkButton" id="start_timer">
                            <property name="label" translatable="yes">Start</property>
                            <property name="visible">True</property>
                            <property name="can-focus">True</property>
                            <property name="receives-default">True</property>
                          </object>
                          <packing>
                            <property name="left-attach">0</property>
                            <property name="top-attach">2</property>
                          </packing>
                        </child>
                        <child>
                          <object class="GtkButton" id="stop_timer">
                            <property name="label" translatable="yes">Stop</property>
                            <property name="visible">True</property>
                            <property name="can-focus">True</property>
                            <property name="receives-default">True</property>
                          </object>
                          <packing>
                            <property name="left-attach">1</property>
                            <property name="top-attach">2</property>
                          </packing>
                        </child>
                        <child>
                          <object class="GtkButton" id="restart_timer">
                            <property name="label" translatable="yes">Restart</property>
                            <property name="visible">True</property>
                            <property name="can-focus">True</property>
                            <property name="receives-default">True</property>
                          </object>
                          <packing>
                            <property name="left-attach">2</property>
                            <property name="top-attach">2</property>
                          </packing>
                        </child>
                        <child>
                          <object class="GtkButton" id="add_timer">
                            <property name="label" translatable="yes">+</property>
                            <property name="visible">True</property>
                            <property name="can-focus">True</property>
                            <property name="receives-default">True</property>
                          </object>
                          <packing>
                            <property name="left-attach">3</property>
                            <property name="top-attach">0</property>
                            <property name="height">3</property>
                          </packing>
                        </child>
                        <child>
                          <object class="GtkLabel" id="timer_display">
                            <property name="visible">True</property>
                            <property name="can-focus">False</property>
                            <property name="hexpand">True</property>
                            <property name="vexpand">True</property>
                          </object>
                          <packing>
                            <property name="left-attach">0</property>
                            <property name="top-attach">1</property>
                            <property name="width">3</property>
                          </packing>
                        </child>
                      </object>
                    </child>
                  </object>
                </child>
              </object>
              <packing>
                <property name="expand">True</property>
                <property name="fill">True</property>
                <property name="position">1</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkBox">
            <property name="visible">True</property>
            <property name="can-focus">False</property>
            <property name="orientation">vertical</property>
            <child>
              <object class="GtkLabel">
                <property name="visible">True</property>
                <property name="can-focus">False</property>
                <property name="label" translatable="yes">activity limit</property>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkScrolledWindow">
                <property name="visible">True</property>
                <property name="can-focus">True</property>
                <property name="shadow-type">in</property>
                <child>
                  <object class="GtkViewport">
                    <property name="visible">True</property>
                    <property name="can-focus">False</property>
                    <child>
                      <!-- n-columns=4 n-rows=3 -->
                      <object class="GtkGrid">
                        <property name="visible">True</property>
                        <property name="can-focus">False</property>
                        <child>
                          <object class="GtkEntry">
                            <property name="visible">True</property>
                            <property name="can-focus">True</property>
                            <property name="hexpand">True</property>
                          </object>
                          <packing>
                            <property name="left-attach">0</property>
                            <property name="top-attach">0</property>
                            <property name="width">3</property>
                          </packing>
                        </child>
                        <child>
                          <object class="GtkButton">
                            <property name="label" translatable="yes">Start</property>
                            <property name="visible">True</property>
                            <property name="can-focus">True</property>
                            <property name="receives-default">True</property>
                          </object>
                          <packing>
                            <property name="left-attach">0</property>
                            <property name="top-attach">2</property>
                          </packing>
                        </child>
                        <child>
                          <object class="GtkButton">
                            <property name="label" translatable="yes">Stop</property>
                            <property name="visible">True</property>
                            <property name="can-focus">True</property>
                            <property name="receives-default">True</property>
                          </object>
                          <packing>
                            <property name="left-attach">1</property>
                            <property name="top-attach">2</property>
                          </packing>
                        </child>
                        <child>
                          <object class="GtkButton">
                            <property name="label" translatable="yes">Restart</property>
                            <property name="visible">True</property>
                            <property name="can-focus">True</property>
                            <property name="receives-default">True</property>
                          </object>
                          <packing>
                            <property name="left-attach">2</property>
                            <property name="top-attach">2</property>
                          </packing>
                        </child>
                        <child>
                          <object class="GtkButton">
                            <property name="label" translatable="yes">+</property>
                            <property name="visible">True</property>
                            <property name="can-focus">True</property>
                            <property name="receives-default">True</property>
                          </object>
                          <packing>
                            <property name="left-attach">3</property>
                            <property name="top-attach">0</property>
                            <property name="height">3</property>
                          </packing>
                        </child>
                        <child>
                          <object class="GtkLabel">
                            <property name="visible">True</property>
                            <property name="can-focus">False</property>
                            <property name="hexpand">True</property>
                            <property name="vexpand">True</property>
                          </object>
                          <packing>
                            <property name="left-attach">0</property>
                            <property name="top-attach">1</property>
                            <property name="width">3</property>
                          </packing>
                        </child>
                      </object>
                    </child>
                  </object>
                </child>
              </object>
              <packing>
                <property name="expand">True</property>
                <property name="fill">True</property>
                <property name="position">1</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">1</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>

execution stack from gdb, yellow行指示最后执行的代码

bellow is the code according to execution flow and some gdb output, the most relevant functions are start_timer, stop_timer and timeout_timer from Time_Keeper and UI_Controller

u-i-controller.h

#ifndef _U_I_CONTROLLER_H_
#define _U_I_CONTROLLER_H_

#include <unistd.h>
#include <gtkmm.h>
#include <unordered_map>
#include <glibmm/datetime.h>
#include <time-keeper.h>


namespace std{
    template <>
    struct hash<Time_Keeper>
    {
        size_t operator()( Time_Keeper& t) const
        {
            return t.hasheable().hash();
        }
    };
}

class UI_Controller
{
public:
    UI_Controller(Gtk::Builder* refference,Gtk::Application * app);
    void deffine_application(Gtk::Application * app);
    void add_window_to_application(Gtk::Window * window);
protected:

private:
    Gtk::Builder * refference;
    Gtk::ApplicationWindow * content_relations;
    Gtk::Application * app;
    std::vector<Glib::RefPtr<Glib::Object>> widgets;
    std::unordered_map<int,Time_Keeper> bind_time;
    void show_window(Gtk::Window *window);
    void start_timer(Gtk::Widget * selected, int position);
    void stop_timer(int i) { (bind_time[i]).stop_timer (); };
    void restart_timer(int i) { return ;}; // to be done
    void add_timer(int i) { return ;}; //to be done
    bool timeout_timer(Gtk::Label * display,int position);
};

#endif // _U_I_CONTROLLER_H_

u-i-controller.cc

#include "u-i-controller.h"

UI_Controller::UI_Controller(Gtk::Builder * refference, Gtk::Application * app)
{
    deffine_application (app);
    this->refference = refference;
    refference->get_widget("main_window",this->content_relations);
    widgets = refference->get_objects();
    Glib::ustring widget_names = "";
    for (int i=0; i < widgets.size(); i++){
        widget_names = widget_names+dynamic_cast<Gtk::Widget*>(widgets.at(i).get())->get_name()+"\n";
        if (dynamic_cast<Gtk::Buildable*>(widgets.at(i).get())->get_name() == (Glib::ustring) "start_timer"){
            //dynamic_cast<Gtk::Widget*>(widgets.at(i).get())->get_ancestor(GTK_TYPE_BOX)
            //dynamic_cast<Gtk::Button*>(widgets.at(i).get())->signal_clicked().connect(sigc::mem_fun(*this,&Controlador_UI::botao_acionado));
            dynamic_cast<Gtk::Button*>(widgets.at(i).get())->signal_clicked().connect(sigc::bind<Gtk::Widget*>(sigc::mem_fun(*this,&UI_Controller::start_timer),dynamic_cast<Gtk::Widget*>(widgets.at(i).get()),i ) );
        }
        if (dynamic_cast<Gtk::Buildable*>(widgets.at(i).get())->get_name() == (Glib::ustring) "stop_timer"){
            dynamic_cast<Gtk::Button*>(widgets.at(i).get())->signal_clicked().connect(sigc::bind(sigc::mem_fun(*this,&UI_Controller::stop_timer),i ) );
        }
        if (dynamic_cast<Gtk::Buildable*>(widgets.at(i).get())->get_name() == (Glib::ustring) "restart_timer"){
            dynamic_cast<Gtk::Button*>(widgets.at(i).get())->signal_clicked().connect(sigc::bind(sigc::mem_fun(*this,&UI_Controller::restart_timer),i ) );
        }
        if (dynamic_cast<Gtk::Buildable*>(widgets.at(i).get())->get_name() == (Glib::ustring) "add_timer"){
            dynamic_cast<Gtk::Button*>(widgets.at(i).get())->signal_clicked().connect(sigc::bind(sigc::mem_fun(*this,&UI_Controller::add_timer),i ) );
        }
    }
    app->run();
}

void UI_Controller::deffine_application(Gtk::Application * app)
{
    this->app = app;
}

void UI_Controller::add_window_to_application (Gtk::Window * window)
{
    app->add_window(*window);
}

void UI_Controller::show_window(Gtk::Window * window)
{
    add_window_to_application(window);
    window->show();
    window->show_all_children();
}

void UI_Controller::start_timer(Gtk::Widget * selected, int position){
    if (bind_time.find(position) == bind_time.end() ){
        bind_time [position] = *(new Time_Keeper());
        (bind_time [position]).start_timer ();
    }
    Gtk::Label * display;
    refference->get_widget("timer_display",display);

    // both 2 variables bellow yet to be managed by this class

    sigc::slot<bool()> my_slot = sigc::bind(sigc::mem_fun(*this,
              &UI_Controller::timeout_timer), display, position);
    auto conn = Glib::signal_timeout().connect(my_slot, 100);
}

bool UI_Controller::timeout_timer(Gtk::Label * display,int position){
    if ( ((bind_time [position]).get_active()) ) display->set_text((bind_time [position]).display_timer ());
    return (bind_time [position]).get_active();
}

reduced Time_Keeper class

#ifndef _TIME_KEEPER_H_
#define _TIME_KEEPER_H_

#include <glibmm/datetime.h>
#include<memory>
#include <glibmm/timer.h>

class Time_Keeper
{
public:
    void start_timer();
    void stop_timer();
    // I would rather use the constructor, but I need a default one in order \
    to use the unordered list
    Glib::DateTime hasheable() { return Glib::DateTime::create_now_local(); }
    bool get_active() { return active; };
protected:

private:
    std::shared_ptr<Glib::Timer> timer;
    bool active = false;
};

#endif // _TIME_KEEPER_H_
#include "time-keeper.h"

void Time_Keeper::start_timer(){
    active = true;
    timer = std::shared_ptr<Glib::Timer>(new Glib::Timer);
    timer.get()->start(); 
};

void Time_Keeper::stop_timer(){
    active = false;
    timer.get()->stop();
}

main

#include <gtkmm.h>
#include <iostream>

#include "config.h"


#ifdef ENABLE_NLS
#  include <libintl.h>
#endif

#include "u-i-controller.h"

/* For testing propose use the local (not installed) ui file */
/* #define UI_FILE PACKAGE_DATA_DIR"/ui/time_keeper.ui" */
#define UI_FILE "src/time_keeper.ui"

Gtk::ApplicationWindow * main_win = 0;

void activate_app(Gtk::Application * app)
{
    app->add_window(*main_win);
    main_win->show();
    main_win->show_all_children ();
}

int
main (int argc, char *argv[])
{
    
    auto app = Gtk::Application::create(argc,argv,"org.gtkmm.time_keeper");

    //Load the Glade file and instiate its widgets:
    Glib::RefPtr<Gtk::Builder> builder;
    try
    {
        builder = Gtk::Builder::create_from_file(UI_FILE);
    }
    catch (const Glib::FileError & ex)
    {
        std::cerr << ex.what() << std::endl;
        return 1;
    }
    
    builder->get_widget("main_window", main_win);

    if (main_win)
    {
        app->signal_startup().connect(sigc::bind<Gtk::Application*>(sigc::ptr_fun(&activate_app), app.get() ) );
        UI_Controller * controller = new UI_Controller(builder.get(),app.get());
    }
}

time_keeper.ui

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.38.2 -->
<interface>
  <requires lib="gtk+" version="3.24"/>
  <object class="GtkApplicationWindow" id="main_window">
    <property name="can-focus">False</property>
    <child>
      <object class="GtkBox">
        <property name="visible">True</property>
        <property name="can-focus">False</property>
        <property name="orientation">vertical</property>
        <property name="spacing">13</property>
        <property name="homogeneous">True</property>
        <child>
          <object class="GtkBox">
            <property name="visible">True</property>
            <property name="can-focus">False</property>
            <property name="orientation">vertical</property>
            <child>
              <object class="GtkLabel">
                <property name="visible">True</property>
                <property name="can-focus">False</property>
                <property name="label" translatable="yes">current activity time</property>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkScrolledWindow">
                <property name="visible">True</property>
                <property name="can-focus">True</property>
                <property name="shadow-type">in</property>
                <child>
                  <object class="GtkViewport">
                    <property name="visible">True</property>
                    <property name="can-focus">False</property>
                    <child>
                      <!-- n-columns=4 n-rows=3 -->
                      <object class="GtkGrid" id="timer_grid">
                        <property name="visible">True</property>
                        <property name="can-focus">False</property>
                        <child>
                          <object class="GtkEntry">
                            <property name="visible">True</property>
                            <property name="can-focus">True</property>
                            <property name="hexpand">True</property>
                          </object>
                          <packing>
                            <property name="left-attach">0</property>
                            <property name="top-attach">0</property>
                            <property name="width">3</property>
                          </packing>
                        </child>
                        <child>
                          <object class="GtkButton" id="start_timer">
                            <property name="label" translatable="yes">Start</property>
                            <property name="visible">True</property>
                            <property name="can-focus">True</property>
                            <property name="receives-default">True</property>
                          </object>
                          <packing>
                            <property name="left-attach">0</property>
                            <property name="top-attach">2</property>
                          </packing>
                        </child>
                        <child>
                          <object class="GtkButton" id="stop_timer">
                            <property name="label" translatable="yes">Stop</property>
                            <property name="visible">True</property>
                            <property name="can-focus">True</property>
                            <property name="receives-default">True</property>
                          </object>
                          <packing>
                            <property name="left-attach">1</property>
                            <property name="top-attach">2</property>
                          </packing>
                        </child>
                        <child>
                          <object class="GtkButton" id="restart_timer">
                            <property name="label" translatable="yes">Restart</property>
                            <property name="visible">True</property>
                            <property name="can-focus">True</property>
                            <property name="receives-default">True</property>
                          </object>
                          <packing>
                            <property name="left-attach">2</property>
                            <property name="top-attach">2</property>
                          </packing>
                        </child>
                        <child>
                          <object class="GtkButton" id="add_timer">
                            <property name="label" translatable="yes">+</property>
                            <property name="visible">True</property>
                            <property name="can-focus">True</property>
                            <property name="receives-default">True</property>
                          </object>
                          <packing>
                            <property name="left-attach">3</property>
                            <property name="top-attach">0</property>
                            <property name="height">3</property>
                          </packing>
                        </child>
                        <child>
                          <object class="GtkLabel" id="timer_display">
                            <property name="visible">True</property>
                            <property name="can-focus">False</property>
                            <property name="hexpand">True</property>
                            <property name="vexpand">True</property>
                          </object>
                          <packing>
                            <property name="left-attach">0</property>
                            <property name="top-attach">1</property>
                            <property name="width">3</property>
                          </packing>
                        </child>
                      </object>
                    </child>
                  </object>
                </child>
              </object>
              <packing>
                <property name="expand">True</property>
                <property name="fill">True</property>
                <property name="position">1</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkBox">
            <property name="visible">True</property>
            <property name="can-focus">False</property>
            <property name="orientation">vertical</property>
            <child>
              <object class="GtkLabel">
                <property name="visible">True</property>
                <property name="can-focus">False</property>
                <property name="label" translatable="yes">activity limit</property>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkScrolledWindow">
                <property name="visible">True</property>
                <property name="can-focus">True</property>
                <property name="shadow-type">in</property>
                <child>
                  <object class="GtkViewport">
                    <property name="visible">True</property>
                    <property name="can-focus">False</property>
                    <child>
                      <!-- n-columns=4 n-rows=3 -->
                      <object class="GtkGrid">
                        <property name="visible">True</property>
                        <property name="can-focus">False</property>
                        <child>
                          <object class="GtkEntry">
                            <property name="visible">True</property>
                            <property name="can-focus">True</property>
                            <property name="hexpand">True</property>
                          </object>
                          <packing>
                            <property name="left-attach">0</property>
                            <property name="top-attach">0</property>
                            <property name="width">3</property>
                          </packing>
                        </child>
                        <child>
                          <object class="GtkButton">
                            <property name="label" translatable="yes">Start</property>
                            <property name="visible">True</property>
                            <property name="can-focus">True</property>
                            <property name="receives-default">True</property>
                          </object>
                          <packing>
                            <property name="left-attach">0</property>
                            <property name="top-attach">2</property>
                          </packing>
                        </child>
                        <child>
                          <object class="GtkButton">
                            <property name="label" translatable="yes">Stop</property>
                            <property name="visible">True</property>
                            <property name="can-focus">True</property>
                            <property name="receives-default">True</property>
                          </object>
                          <packing>
                            <property name="left-attach">1</property>
                            <property name="top-attach">2</property>
                          </packing>
                        </child>
                        <child>
                          <object class="GtkButton">
                            <property name="label" translatable="yes">Restart</property>
                            <property name="visible">True</property>
                            <property name="can-focus">True</property>
                            <property name="receives-default">True</property>
                          </object>
                          <packing>
                            <property name="left-attach">2</property>
                            <property name="top-attach">2</property>
                          </packing>
                        </child>
                        <child>
                          <object class="GtkButton">
                            <property name="label" translatable="yes">+</property>
                            <property name="visible">True</property>
                            <property name="can-focus">True</property>
                            <property name="receives-default">True</property>
                          </object>
                          <packing>
                            <property name="left-attach">3</property>
                            <property name="top-attach">0</property>
                            <property name="height">3</property>
                          </packing>
                        </child>
                        <child>
                          <object class="GtkLabel">
                            <property name="visible">True</property>
                            <property name="can-focus">False</property>
                            <property name="hexpand">True</property>
                            <property name="vexpand">True</property>
                          </object>
                          <packing>
                            <property name="left-attach">0</property>
                            <property name="top-attach">1</property>
                            <property name="width">3</property>
                          </packing>
                        </child>
                      </object>
                    </child>
                  </object>
                </child>
              </object>
              <packing>
                <property name="expand">True</property>
                <property name="fill">True</property>
                <property name="position">1</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">1</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>

execution stack from gdb, yellow line indicates the last executed code
executiom stack from gdb

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

七色彩虹 2025-02-07 07:35:06

基于nodakker的答案,我发现我在

if (dynamic_cast<Gtk::Buildable*>(widgets.at(i).get())->get_name() == (Glib::ustring) "stop_timer"){
            dynamic_cast<Gtk::Button*>(widgets.at(i).get())->signal_clicked().connect(sigc::bind(sigc::mem_fun(*this,&UI_Controller::stop_timer),i ) );
        }

向量小部件上出现错误的位置start_timer and stop_timer具有不同的值,因此我最终在start_timer内部的表达式上创建了映射bind_time,该参数与index值相对应,该参数与索引值相对应存储的按钮start_timer,但是当我执行stop_timer时,我最终试图在索引的time_keeper上进行操作,实际上与widgets vector上的stop_timer索引相对应,time_keeper不存在,null以null

以解决问题,现在解决问题。循环我一直在到达按钮所在的gtk ::网格,然后根据它们在网格上的固定位置访问它们。关于其他最简单的替代方案,获得按钮所在的网格索引,我知道有效

based on NoDakker answer I found where my mistake was on

if (dynamic_cast<Gtk::Buildable*>(widgets.at(i).get())->get_name() == (Glib::ustring) "stop_timer"){
            dynamic_cast<Gtk::Button*>(widgets.at(i).get())->signal_clicked().connect(sigc::bind(sigc::mem_fun(*this,&UI_Controller::stop_timer),i ) );
        }

on the vector widgets the buttons start_timer and stop_timer have different values, so I end up creating the map bind_time, on an expression inside start_timer with the parameter corresponding with the index value on vector widgets of the stored button start_timer, however when I execute stop_timer I end up trying to do operations on the Time_Keeper of the index actually corresponding to the index of stop_timer on the widgets vector, that Time_Keeper is non existent, NULL

To solve the problem now on the for loop I am going just until it reaches the Gtk::Grid where the buttons are in and then I access them based on their fixed positions on the grid. Regarding the other alternatives that is the most simple to get the index of the grid where the buttons are located and that I know that works

不忘初心 2025-02-07 07:35:06

我对C ++的经验不太有经验,但是我拿了您的代码,并建立了时间守护程序,以使其在开始和停止操作中行动。按下“停止”按钮时,我也得到了细分错误。因此,我添加了一些“ cout”语句以跟踪“ start_timer”和“ stop_timer”功能中的对象指针。我发现的是计时器对象的“ start_timer”函数中设置了指针参考。但是,在执行互补的“ stop_timer”函数(为null)时,找不到此指针参考。以下是开始执行和停止执行的终端输出。

Entered timer start
Time keeper timer pointer value: %p0x55dfd78fb390
Entered timer stop
Time keeper timer pointer value: %p0
Segmentation fault (core dumped)

仅对于测试用例,我立即在“ main.cc”程序中创建了一个测试时间守护者对象,调用“ start_timer”和“ stop_timer”。

Time_Keeper *test = new Time_Keeper();
std::cout << "Test time keeper address %p" << test << std::endl;
test->start_timer();
test->stop_timer();

这导致了计时器的正确关闭,而无需分段故障。

Test time keeper address %p0x55dfd7847e50
Entered timer start
Time keeper timer pointer value: %p0x55dfd789e100
Entered timer stop
Time keeper pointer value: %p0x55dfd789e100

我不能肯定地说,但是要么需要对启动计时器函数进行同步,要么将停止计时器函数用于相同的映射迭代。作为一个简单的解决方法,我在“ ui-controller.h”文件中添加了一个静态整数变量,以在启动计时器时跟踪迭代参考。

static int poss = 0;

在调用“ stop_timer”函数时,将索引设置为此静态整数,而不是顺序输入值。

void stop_timer(int i)
{
    (bind_time[poss]).stop_timer ();
}

然后在“ ui-controller.cc”文件中,在启动计时器时设置此静态变量。

    if (bind_time.find(position) == bind_time.end() )
    {
        poss = position;  // Save the timer iteration position.
        bind_time [position] = *(new Time_Keeper());
        (bind_time [position]).start_timer ();
    }

这不是最优雅的处理方式,因为我确定可能有更好的方法可以使事情保持一致。但这暂时完成了工作。

希望这不会太杂乱无章,并派往正确的方向。

问候。

I am not too experienced with C++, but I took your code and built the time keeper program to walk it through the start and stop actions. I too got the segmentation fault when the "Stop" button was pressed. So, I added some "cout" statements to track object pointers within the "start_timer" and "stop_timer" functions. What I found was a pointer reference was set up within the "start_timer" function for the timer object. But this pointer reference was not found when executing the complementary "stop_timer" function (it was NULL). Following was the terminal output for the start and stop execution.

Entered timer start
Time keeper timer pointer value: %p0x55dfd78fb390
Entered timer stop
Time keeper timer pointer value: %p0
Segmentation fault (core dumped)

Just for a test case, I created a test time keeper object immediately within the "main.cc" program, calling "start_timer" and "stop_timer".

Time_Keeper *test = new Time_Keeper();
std::cout << "Test time keeper address %p" << test << std::endl;
test->start_timer();
test->stop_timer();

This resulted in a proper shutdown of the timer without a segmentation fault.

Test time keeper address %p0x55dfd7847e50
Entered timer start
Time keeper timer pointer value: %p0x55dfd789e100
Entered timer stop
Time keeper pointer value: %p0x55dfd789e100

I can't say for sure, but either there needs to be a synchronization of the start timer function and the stop timer function to the same mapping iteration. As a simple workaround, I added a static integer variable to the "u-i-controller.h" file to keep track of the iteration reference when the timer was started.

static int poss = 0;

At the point of calling the "stop_timer" function, the index is set to this static integer instead of the sequential input value.

void stop_timer(int i)
{
    (bind_time[poss]).stop_timer ();
}

Then within the "u-i-controller.cc" file, this static variable is set when the timer is started.

    if (bind_time.find(position) == bind_time.end() )
    {
        poss = position;  // Save the timer iteration position.
        bind_time [position] = *(new Time_Keeper());
        (bind_time [position]).start_timer ();
    }

This isn't the most elegant way to handle this as I am sure there are probably better ways to keep things aligned. But it gets the job done for now.

This hopefully wasn't too rambling and sends you in the right direction.

Regards.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文