Interesting wxChoice problem (GTK 2.8.0)

Stephan Rose kermos at somrek.net
Sat Mar 3 17:16:03 PST 2007


While testing my app under GTK Today, ran into an interesting issue with 
wxChoice.

My app kept crashing trying to call GetClientData() so after spending some 
time debugging I found the cause. GetClientData() was returning NULL for some 
items but not all items.

I am adding multiple items via Append() and every single item has client data. 
So normally, there is no way any GetClientData should ever return NULL as 
long as the index is valid.

Since the loop iterates from 0 to the value returned from GetCount() the index 
should always be valid.

So I started stepping through the Append() function call with the debugger and 
found the cause.

It seems that wxChoice is adding the item..sorting the list...and then 
returning an index for the item. The list however that contains the client 
data does not seem to be sorted the same causing the subsequent 
DoSetItemClientData to add the the wrong index in the list, over-writing the 
m_data pointer of the wrong client item. I was actually able to see this 
happening in the debugger.

If I remove wxCB_SORT from the style everything works correctly.

Here is the code:

comboElectricalType	 = new wxChoice(this, idComboElectricalType, 
wxDefaultPosition, wxDefaultSize, 0, NULL );
// defined as wxChoice* in the class header

comboElectricalType->Append(_("Bi-Directional"), 	
&pinElectricalTypeBidirectional);
comboElectricalType->Append(_("Input"), 			&pinElectricalTypeInput);
comboElectricalType->Append(_("Open High"), 		&pinElectricalTypeOpenHigh);
comboElectricalType->Append(_("Open Low"), 			&pinElectricalTypeOpenLow);
comboElectricalType->Append(_("Output"), 			&pinElectricalTypeOutput);
comboElectricalType->Append(_("Passive"), 			&pinElectricalTypePassive);
comboElectricalType->Append(_("Passive High"), 		
&pinElectricalTypePassiveHigh);
comboElectricalType->Append(_("Passive Low"), 		&pinElectricalTypePassiveLow);
comboElectricalType->Append(_("Power"), 			&pinElectricalTypePower);
comboElectricalType->Append(_("3-State"), 			&pinElectricalTypeTriState);
comboElectricalType->Append(_("Unknown"), 			&pinElectricalTypeUnknown);
SetComboChoice(comboElectricalType, pinElectricalType);	

The various pin variables are all defined as a 4 byte integer that stores the 
ID for the respective type.

Following that is a call that sets the choice to the current active choice.

bool EditPinDialog::SetComboChoice(wxChoice* combo, s32 choice)
{
	for(unsigned int i = 0; i < combo->GetCount(); i++)
	{
		s32 data = *((s32*)combo->GetClientData(i));

		if(choice == data)
		{			
			combo->Select(i);
			return true;
		}
	}
	return false;
}

The code will crash on the GetClientData line if it returns NULL but since 
there normally is no way that should ever happen I don't bother checking for 
it.

Under MSW it performs 100% correctly which is why I was really confused at 
first. Checking the choice.cpp code for MSW though I saw that it is 
completely different from the GTK version which explains the difference in 
behavior and reassured me that I am not going insane just yet. =)

Any thoughts? 

Thanks,

Stephan




More information about the wx-users mailing list