Hi Sander,
This happens because you have redefined __PCL_DIAGNOSTICS_LEVEL to something different from zero. PCL diagnostics code works well in general, but there are some small errors as the one you've discovered. This is a precondition failed in the following member function of Allocator:
void Allocator::Deallocate( T* p )
{
PCL_PRECONDITION( p != 0 )
this->DeallocateBlock( (void*)p );
}
The precondition signals that a zero pointer has been passed to Allocator::Deallocate(), which is a formal error. However, there's no problem because DeallocateBlock() (as reimplemented by pcl::StandardAllocator) protects itself from this contingency. I'll investigate where this null pointer deallocation attempt comes from; thanks for catching it.
To avoid these problems, just don't use diagnostics code (don't redefine __PCL_DIAGNOSTICS_LEVEL) and everything should work fine.
I have prepared a small example to test PCL file dialogs. It is a modified version of SandBox:
Modified SandBoxInterface.h:
#ifndef __SandboxInterface_h
#define __SandboxInterface_h
#include <pcl/ProcessingInterface.h>
#include <pcl/Sizer.h>
#include <pcl/PushButton.h>
#include <pcl/Edit.h>
#include <pcl/TextBox.h>
#include "SandboxInstance.h"
namespace pcl
{
class SandboxInterface : public ProcessingInterface
{
public:
SandboxInterface();
virtual ~SandboxInterface();
virtual IsoString Id() const;
virtual uint32 Version() const;
virtual const char** IconImageXPM() const;
virtual void ApplyInstance() const;
virtual void ResetInstance();
virtual bool Launch( const MetaProcess&, const ProcessImplementation*, bool& dynamic, unsigned& /*flags*/ );
virtual ProcessImplementation* NewProcess() const;
virtual bool ValidateProcess( const ProcessImplementation&, String& whyNot ) const;
virtual bool RequiresInstanceValidation() const;
virtual bool ImportProcess( const ProcessImplementation& );
private:
SandboxInstance instance;
struct GUIData
{
GUIData( SandboxInterface& );
VerticalSizer Global_Sizer;
PushButton TestSaveFileDialog_PushButton;
Edit TestSaveFileDialog_Edit;
PushButton TestOpenFileDialog_PushButton;
Edit TestOpenFileDialog_Edit;
PushButton TestOpenFilesDialog_PushButton;
TextBox TestOpenFilesDialog_TextBox;
};
GUIData* GUI;
void UpdateControls();
// Event Handlers
void __ItemClicked( Button& sender, bool checked );
friend struct GUIData;
};
// ----------------------------------------------------------------------------
PCL_BEGIN_LOCAL
extern SandboxInterface* TheSandboxInterface;
PCL_END_LOCAL
// ----------------------------------------------------------------------------
} // pcl
#endif // __SandboxInterface_h
Modified SandBoxInterface.cpp:
#include "SandboxInterface.h"
#include "SandboxProcess.h"
#include "SandboxParameters.h"
#include <pcl/FileDialog.h>
namespace pcl
{
// ----------------------------------------------------------------------------
SandboxInterface* TheSandboxInterface = 0;
// ----------------------------------------------------------------------------
SandboxInterface::SandboxInterface() :
ProcessingInterface(), instance( TheSandboxProcess ), GUI( 0 )
{
TheSandboxInterface = this;
}
SandboxInterface::~SandboxInterface()
{
if ( GUI != 0 )
delete GUI, GUI = 0;
}
IsoString SandboxInterface::Id() const
{
return "Sandbox";
}
uint32 SandboxInterface::Version() const
{
return 0x100; // required
}
const char** SandboxInterface::IconImageXPM() const
{
return 0; // SandboxIcon_XPM; ---> put a nice icon here
}
void SandboxInterface::ApplyInstance() const
{
instance.LaunchOnCurrentView();
}
void SandboxInterface::ResetInstance()
{
SandboxInstance defaultInstance( TheSandboxProcess );
ImportProcess( defaultInstance );
}
bool SandboxInterface::Launch( const MetaProcess& P, const ProcessImplementation*, bool& dynamic, unsigned& /*flags*/ )
{
// ### Deferred initialization
if ( GUI == 0 )
{
GUI = new GUIData( *this );
SetWindowTitle( "Sandbox" );
UpdateControls();
}
dynamic = false;
return &P == TheSandboxProcess;
}
ProcessImplementation* SandboxInterface::NewProcess() const
{
return new SandboxInstance( instance );
}
bool SandboxInterface::ValidateProcess( const ProcessImplementation& p, String& whyNot ) const
{
const SandboxInstance* r = dynamic_cast<const SandboxInstance*>( &p );
if ( r == 0 )
{
whyNot = "Not a Sandbox instance.";
return false;
}
whyNot.Empty();
return true;
}
bool SandboxInterface::RequiresInstanceValidation() const
{
return true;
}
bool SandboxInterface::ImportProcess( const ProcessImplementation& p )
{
instance.Assign( p );
UpdateControls();
return true;
}
// ----------------------------------------------------------------------------
void SandboxInterface::UpdateControls()
{
}
// ----------------------------------------------------------------------------
static void SetCSVFiltersHelper( FileDialog& dialog )
{
FileFilter csvFilter;
csvFilter.SetDescription( "CSV files" );
csvFilter.AddExtension( ".csv" );
FileFilter txtFilter;
txtFilter.SetDescription( "Plain text files" );
txtFilter.AddExtension( ".txt" );
dialog.Filters().Add( csvFilter );
dialog.Filters().Add( txtFilter );
}
void SandboxInterface::__ItemClicked( Button& sender, bool checked )
{
if ( sender == GUI->TestSaveFileDialog_PushButton )
{
SaveFileDialog theDialog;
theDialog.SetCaption( "Select a file name to save the CSV to" );
SetCSVFiltersHelper( theDialog );
if ( theDialog.Execute() )
GUI->TestSaveFileDialog_Edit.SetText( theDialog.FileName() );
}
else if ( sender == GUI->TestOpenFileDialog_PushButton )
{
OpenFileDialog theDialog;
theDialog.SetCaption( "Select a CSV or plain text file to open" );
SetCSVFiltersHelper( theDialog );
if ( theDialog.Execute() )
GUI->TestOpenFileDialog_Edit.SetText( theDialog.FileName() );
}
else if ( sender == GUI->TestOpenFilesDialog_PushButton )
{
OpenFileDialog theDialog;
theDialog.SetCaption( "Select a set of CSV or plain text files to open" );
theDialog.EnableMultipleSelections();
SetCSVFiltersHelper( theDialog );
if ( theDialog.Execute() )
{
String fileNames;
for ( StringList::const_iterator i = theDialog.FileNames().Begin();
i != theDialog.FileNames().End();
++i )
{
fileNames += *i;
fileNames += '\n';
}
fileNames += "<beg>"; // to scroll the TextBox to the beginning
GUI->TestOpenFilesDialog_TextBox.SetText( fileNames );
}
}
}
// ----------------------------------------------------------------------------
SandboxInterface::GUIData::GUIData( SandboxInterface& w )
{
TestSaveFileDialog_PushButton.SetText( "Test SaveFileDialog" );
TestSaveFileDialog_PushButton.OnClick( (pcl::Button::click_event_handler)&SandboxInterface::__ItemClicked, w );
TestSaveFileDialog_Edit.SetReadOnly();
TestSaveFileDialog_Edit.SetMinWidth( 400 );
TestOpenFileDialog_PushButton.SetText( "Test OpenFileDialog - Single Selection" );
TestOpenFileDialog_PushButton.OnClick( (pcl::Button::click_event_handler)&SandboxInterface::__ItemClicked, w );
TestOpenFileDialog_Edit.SetReadOnly();
TestOpenFileDialog_Edit.SetMinWidth( 400 );
TestOpenFilesDialog_PushButton.SetText( "Test OpenFileDialog - Multiple Selections" );
TestOpenFilesDialog_PushButton.OnClick( (pcl::Button::click_event_handler)&SandboxInterface::__ItemClicked, w );
TestOpenFilesDialog_TextBox.SetReadOnly();
TestOpenFilesDialog_TextBox.SetMinSize( 400, 200 );
//
Global_Sizer.SetMargin( 8 );
Global_Sizer.SetSpacing( 6 );
Global_Sizer.Add( TestSaveFileDialog_PushButton );
Global_Sizer.Add( TestSaveFileDialog_Edit );
Global_Sizer.Add( TestOpenFileDialog_PushButton );
Global_Sizer.Add( TestOpenFileDialog_Edit );
Global_Sizer.Add( TestOpenFilesDialog_PushButton );
Global_Sizer.Add( TestOpenFilesDialog_TextBox );
w.SetSizer( Global_Sizer );
w.AdjustToContents();
}
// ----------------------------------------------------------------------------
} // pcl