SpinCtrl->GetValue() makes the program crash

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
Wanderer82
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 670
Joined: Tue Jul 26, 2016 2:00 pm

SpinCtrl->GetValue() makes the program crash

Post by Wanderer82 »

Hello

I ran into a new problem. While initializing a new wxdialog I create elements dynamically. I also create different SpinCtrls like this. Each product has a SpinCtrl.

Now if someone puts the product into the shopping cart, the value should be read from that SpinCtrl. But it always crashes my program. Also setting the SpinCtrl again crashes the program even though during the initializing process it works fine.

Code: Select all

#include "Geometrie.h"
#include <wx/msgdlg.h>
#include "Produkt.h"
#include <string>
#include <wx/msgdlg.h>
#include <sstream>
#include <fstream>
#include <iostream>
#include <wx/log.h>
#include "Warenkorb.h"

int erstesProduktGeometrie;
int letztesProduktGeometrie;

void first_last_product_Geometrie(string category)
{
    int a = 1;
    string erstesProdukt1;
    string letztesProdukt1;
    string b;

    do
    {
        b = _Produkt[a].readKategorie();
        if (b == category)
            {erstesProduktGeometrie = a;
             erstesProdukt1 = category;
        }else

            a = a + 1;
    }

    while (erstesProduktGeometrie != a && a < 49);

    do
        {
        b = _Produkt[a].readKategorie();
        if (b != category)
        {
            letztesProdukt1 = "anderes";
        }
        else
        {
            letztesProduktGeometrie = a;
            a = a + 1;
        }
        }
    while (letztesProdukt1 != "anderes");
};


//(*InternalHeaders(Geometrie)
#include <wx/intl.h>
#include <wx/bitmap.h>
#include <wx/font.h>
#include <wx/string.h>
#include <wx/image.h>
//*)

//(*IdInit(Geometrie)
const long Geometrie::ID_PANEL1 = wxNewId();
const long Geometrie::ID_STATICTEXT[] = {wxNewId()};
const long Geometrie::ID_STATICBITMAP[] = {wxNewId()};
const long Geometrie::ID_SPINCTRL[] = {wxNewId()};
const long Geometrie::ID_CHOICE1[] = {wxNewId()};
const long Geometrie::ID_CHOICE2[] = {wxNewId()};
//*)

BEGIN_EVENT_TABLE(Geometrie,wxDialog)
	//(*EventTable(Geometrie)
	//*)
END_EVENT_TABLE()

Geometrie::Geometrie(wxWindow* parent,wxWindowID id,const wxPoint& pos,const wxSize& size)
{
	//(*Initialize(Geometrie)
	first_last_product_Geometrie("Geometrie");

	wxFlexGridSizer* FlexGridSizer2;
	wxBoxSizer* BoxSizer2;
	wxBoxSizer* BoxSizer1;
	wxBoxSizer* BoxSizer[50];
	wxFlexGridSizer* FlexGridSizer1;

	Create(parent, wxID_ANY, _("Geometrie"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE, _T("wxID_ANY"));
	SetClientSize(wxDefaultSize);
	Move(wxDefaultPosition);
	BoxSizer1 = new wxBoxSizer(wxVERTICAL);
	Panel1 = new wxPanel(this, ID_PANEL1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, _T("ID_PANEL1"));
	FlexGridSizer1 = new wxFlexGridSizer(0, 3, 0, 0);
	BoxSizer2 = new wxBoxSizer(wxVERTICAL);
	FlexGridSizer2 = new wxFlexGridSizer(0, 4, 0, 0);
	BoxSizer2->Add(FlexGridSizer2, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);

    int Durchlauf = 1;
    int AnzahlDurchlauf = letztesProduktGeometrie - (erstesProduktGeometrie - 1);


    /*ostringstream Str;
    ostringstream Str2;
    ostringstream Str3;
    Str << erstesProduktGeometrie;
    string r(Str.str());
    wxMessageBox("Erstes Produkt: " + r);
    Str2 << letztesProduktGeometrie;
    string t(Str2.str());
    wxMessageBox("Letztes Produkt: " + t);
    Str3 << AnzahlDurchlauf;
    string v(Str3.str());
    wxMessageBox("Anzahl Durchlauf: " + v);*/

	do
    {
    StaticText[erstesProduktGeometrie] = new wxStaticText(Panel1, ID_STATICTEXT[erstesProduktGeometrie], _(_Produkt[erstesProduktGeometrie].readName()), wxDefaultPosition, wxDefaultSize, 0, _T("ID_STATICTEXT[erstesProduktGeometrie]"));
	wxFont StaticTextFont(11,wxFONTFAMILY_SWISS,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_BOLD,false,_T("Calibri"),wxFONTENCODING_DEFAULT);
	StaticText[erstesProduktGeometrie]->SetFont(StaticTextFont);
	FlexGridSizer2->Add(StaticText[erstesProduktGeometrie], 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
	StaticBitmap[erstesProduktGeometrie] = new wxStaticBitmap(Panel1, ID_STATICBITMAP[erstesProduktGeometrie], wxBitmap(wxImage(_Produkt[erstesProduktGeometrie].readProduktbild())), wxDefaultPosition, wxDefaultSize, wxSIMPLE_BORDER, _T("ID_STATICBITMAP1"));
	FlexGridSizer2->Add(StaticBitmap[erstesProduktGeometrie], 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    BoxSizer[erstesProduktGeometrie] = new wxBoxSizer(wxVERTICAL);
    int s = 0; //Zähler für Choice

	if (_Produkt[erstesProduktGeometrie].readAnzahlOptionen() == 1)
    {

        Choice1[erstesProduktGeometrie] = new wxChoice(Panel1, ID_CHOICE1[erstesProduktGeometrie], wxDefaultPosition, wxSize(72,21), 0, 0, 0, wxDefaultValidator, _T("ID_CHOICE1[erstesProduktGeometrie]"));
        BoxSizer[erstesProduktGeometrie]->Add(Choice1[erstesProduktGeometrie], 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);

        do
        {
            Choice1[erstesProduktGeometrie]->SetSelection( Choice1[erstesProduktGeometrie]->Append(_(_Produkt[erstesProduktGeometrie].readOptionen(0,s))) );
            s = s + 1;
        }

        while (s < _Produkt[erstesProduktGeometrie].readAnzahlOption(1));
    }

    if (_Produkt[erstesProduktGeometrie].readAnzahlOptionen() == 2)
    {
        Choice1[erstesProduktGeometrie] = new wxChoice(Panel1, ID_CHOICE1[erstesProduktGeometrie], wxDefaultPosition, wxSize(72,21), 0, 0, 0, wxDefaultValidator, _T("ID_CHOICE1[erstesProduktGeometrie]"));
        BoxSizer[erstesProduktGeometrie]->Add(Choice1[erstesProduktGeometrie], 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);

        do
        {
            Choice1[erstesProduktGeometrie]->SetSelection( Choice1[erstesProduktGeometrie]->Append(_(_Produkt[erstesProduktGeometrie].readOptionen(0,s))) );
            s = s + 1;
        }

        while (s < _Produkt[erstesProduktGeometrie].readAnzahlOption(1));
        s = 0;

        Choice2[erstesProduktGeometrie] = new wxChoice(Panel1, ID_CHOICE2[erstesProduktGeometrie], wxDefaultPosition, wxSize(72,21), 0, 0, 0, wxDefaultValidator, _T("ID_CHOICE2[erstesProduktGeometrie]"));
        BoxSizer[erstesProduktGeometrie]->Add(Choice2[erstesProduktGeometrie], 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);

        do
        {
            Choice2[erstesProduktGeometrie]->SetSelection( Choice2[erstesProduktGeometrie]->Append(_(_Produkt[erstesProduktGeometrie].readOptionen(1,s))) );
            s = s + 1;
        }

        while (s < _Produkt[erstesProduktGeometrie].readAnzahlOption(2));
    }

	SpinCtrl[erstesProduktGeometrie] = new wxSpinCtrl(Panel1, ID_SPINCTRL[erstesProduktGeometrie], _T("0"), wxDefaultPosition, wxSize(72,21), 0, 0, 100, 0, _T("ID_SPINCTRL[erstesProduktGeometrie]"));
	//SpinCtrl[erstesProduktGeometrie]->SetValue(_T("1"));

	BoxSizer[erstesProduktGeometrie]->Add(SpinCtrl[erstesProduktGeometrie], 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
	FlexGridSizer2->Add(BoxSizer[erstesProduktGeometrie], 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
	int button_id = 10000 + erstesProduktGeometrie;
	wxBitmapButton *button = new wxBitmapButton(Panel1, button_id, wxBitmap(wxImage(_T("C:\\Users\\Thomas\\Documents\\Programmprojekte\\Wall-Mat\\warenkorb2.png"))), wxDefaultPosition, wxDefaultSize, wxNO_BORDER, wxDefaultValidator, _T("ID_BITMAPBUTTON[10000]"));
	BitmapButton[erstesProduktGeometrie] = button;
	FlexGridSizer2->Add(button, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
    button->Connect(button_id,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&Geometrie::OnBitmapButtonClick);

	Durchlauf = Durchlauf + 1;
	erstesProduktGeometrie = erstesProduktGeometrie + 1;
    }

	while (Durchlauf < AnzahlDurchlauf + 1);

	FlexGridSizer1->Add(BoxSizer2, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
	Panel1->SetSizer(FlexGridSizer1);
	FlexGridSizer1->Fit(Panel1);
	FlexGridSizer1->SetSizeHints(Panel1);
	BoxSizer1->Add(Panel1, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
	SetSizer(BoxSizer1);
	BoxSizer1->Fit(this);
	BoxSizer1->SetSizeHints(this);
    Center();

	//*)
}

Geometrie::~Geometrie()
{
	//(*Destroy(Geometrie)
	//*)
}

void Geometrie::OnBitmapButtonClick(wxCommandEvent& event)
{
   int Produktnummer_Wahl;
   //wxLogMessage( "you clicked button with id=%d", (event.GetId()-10000));
   Produktnummer_Wahl = (event.GetId()-10000);

   if (_Produkt[(event.GetId()-10000)].readAnzahlOptionen() == 0)
   {
        int SpinCtrlValue;
        SpinCtrl[0]->GetValue();
        /*SpinCtrlValue = SpinCtrl[3]->GetValue();
        _Warenkorb[Warenkorb_count].setWarenkorb(Produktnummer_Wahl, 0, 0, SpinCtrlValue);
   */}
   //wxLogMessage( "you clicked button with id=%d", (event.GetId()-10000));
}
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4193
Joined: Sun Jan 03, 2010 5:45 pm

Re: SpinCtrl->GetValue() makes the program crash

Post by PB »

When a code crashes, you are expected to post a crash message as well as a stack backtrace. When the code crashes accessing a pointer, it is a good chance that the pointer in question is invalid. Or in your case, the index you are using to access the control in the SpinCtrl array is wrong...

Sorry, besides that all I can suggest is that you improve the way you write the code. IMO, the code you posted is very difficult to read which means it will be very difficult to maintain and is rather error-prone.

For starters, I would suggest using meaningful variable names (not e.g., a, b, FlexGridSizer2, or str3) and avoiding using literals (e.g., 49, 10000) -use named constants instead). Speaking of variable names, people also usually pick and stick to one naming convention and capitalization... Using absolute paths in the code is also a bad idea.
User avatar
xaviou
Super wx Problem Solver
Super wx Problem Solver
Posts: 437
Joined: Mon Aug 21, 2006 3:18 pm
Location: Annecy - France
Contact:

Re: SpinCtrl->GetValue() makes the program crash

Post by xaviou »

Hi.

I tried to see what was wrong, bug as PB said in the previous post, it is very hard to understand.

Nevertheless, I think your problem comes from your variable named "erstesProduktGeometrie".

You never initialize it correctly.
In the begenning of your dialog constructor, you make a call to "first_last_product_Geometrie()" and then start creating yoru controls with the modified value of "erstesProduktGeometrie".

So I think the zero-index controls pointers are never set.

I think you should avoid using this global interger var.

Regards
Xav'
My wxWidgets stuff web page : X@v's wxStuff
Wanderer82
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 670
Joined: Tue Jul 26, 2016 2:00 pm

Re: SpinCtrl->GetValue() makes the program crash

Post by Wanderer82 »

Hm, ok I can provide more information... maybe that helps:

If I use the same code...

Code: Select all

SpinCtrl[3]->GetValue();
...at the end of my dialog constructor (after the loops for creating all the elements) it works flawlessly. The program only crashes if I use the same code in the BitmapButton handler. So that's what I don't understand, why is it only there where it won't work?

Maybe the code in my example was a bit misleading (sorry for the zero in the SpinCtrl array, I was just playing around trying to find the problem). But the problem persists if I use other values. So it seems that the SpinCtrl was created correctly if the same code works in the dialog constructor. It has to be something with the BitmapButton, I guess, but that's only a beginner's opinion ;-)

In my build log, after the crash, it just says "Process terminated with status 255". What is a stack backtrack and how can I find / generate it?

BTW: What do you mean by "zero index controls pointers"?
PB
Part Of The Furniture
Part Of The Furniture
Posts: 4193
Joined: Sun Jan 03, 2010 5:45 pm

Re: SpinCtrl->GetValue() makes the program crash

Post by PB »

Wanderer82 wrote:Hm, ok I can provide more information... maybe that helps:

If I use the same code...

Code: Select all

SpinCtrl[3]->GetValue();
...at the end of my dialog constructor (after the loops for creating all the elements) it works flawlessly. The program only crashes if I use the same code in the BitmapButton handler. So that's what I don't understand, why is it only there where it won't work?
You may be connecting the event to the wrong sink
Try changing

Code: Select all

button->Connect(button_id,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&Geometrie::OnBitmapButtonClick);
to

Code: Select all

button->Connect(button_id,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&Geometrie::OnBitmapButtonClick, NULL, this);
or just

Code: Select all

Connect(button_id,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&Geometrie::OnBitmapButtonClick);
It is better to use Bind() instead of Connect(), as you can prevent this kind of bugs...
Last edited by PB on Tue Sep 19, 2017 8:28 am, edited 1 time in total.
Wanderer82
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 670
Joined: Tue Jul 26, 2016 2:00 pm

Re: SpinCtrl->GetValue() makes the program crash

Post by Wanderer82 »

That did the trick ;-)

I don't know "Bind". Is the code the same, do I just have to replace "Connect" with "Bind"?
Post Reply