segmentation fault when using wxClient and wxTCPConnection

3 views
Skip to first unread message

Daniel

unread,
Nov 23, 2009, 6:24:44 PM11/23/09
to wx-users
The segmentation fault occurs on the command below:

void TBClientFrame::Login(const wxString &login, const wxString
&passwd)
{
...
tb_client->GetConnection()->Execute(login + '/' + passwd);
}

Here is the client class with GetConnection:

class TBClient : public wxTCPClient
{
public:
TBClient(void) {}
wxConnectionBase *OnMakeConnection(void)
{ return new TBConnection; }
TBConnection *GetConnection()
{ return tb_connection; }
protected:
TBConnection *tb_connection;
};

And tb_client is declared by the frame:

class TBClientFrame : public wxFrame
{
public:
TBClient *tb_client;

Anybody any ideas as to what might be causing the segmentation fault?

Daniel

unread,
Nov 24, 2009, 4:58:32 PM11/24/09
to wx-users
Just an update. I tried the following to simplify the code but it
still gives a segmentation fault:

wxString tmp = wxT("Hello");
tb_client->GetConnection()->Execute((wxChar*) tmp.c_str());

Daniel

unread,
Nov 24, 2009, 5:09:01 PM11/24/09
to wx-users
I split the code further:

tmpptr = tb_client->GetConnection();
wxMessageBox(wxT("Ready to execute."), wxT(""));
tmpptr->Execute((wxChar*) tmp.c_str());

The seg. fault occurs in on the execute command.

Kenneth Porter

unread,
Nov 24, 2009, 5:13:45 PM11/24/09
to wx-u...@googlegroups.com
--On Tuesday, November 24, 2009 2:09 PM -0800 Daniel <danw...@gmail.com>
wrote:

Use the debug version of the libraries and step down into the library code
to see where it actually fails.


Daniel

unread,
Nov 25, 2009, 4:00:46 PM11/25/09
to wx-users
> > The seg. fault occurs in on the execute command.
>
> Use the debug version of the libraries and step down into the library code
> to see where it actually fails.

OK I set a break point and got the debugger to stop on that line of
code. Now how do I step into the wxWidgets code? By the way, I
looked at some documentation on debugging wxwidgets:
http://docs.wxwidgets.org/trunk/overview_debugging.html
.. it does not make much sense to me. Do I need to define
__WXDEBUG__ ?

Vadim Zeitlin

unread,
Nov 25, 2009, 5:25:51 PM11/25/09
to wx-u...@googlegroups.com
On Wed, 25 Nov 2009 13:00:46 -0800 (PST) Daniel <danw...@gmail.com> wrote:

D> OK I set a break point and got the debugger to stop on that line of
D> code. Now how do I step into the wxWidgets code?

What do you mean? There is nothing special about stepping into wxWidgets
code, you do it in exactly the same way as with any other code.

D> By the way, I looked at some documentation on debugging wxwidgets:
D> http://docs.wxwidgets.org/trunk/overview_debugging.html .. it does not
D> make much sense to me. Do I need to define __WXDEBUG__ ?

I don't know/remember which platform/version do you use but to debug wx
itself you need to build it in debug build, i.e. using --enable-debug when
using configure. You never need to define __WXDEBUG__ manually.

Regards,
VZ

--
TT-Solutions: wxWidgets consultancy and technical support
http://www.tt-solutions.com/

Daniel

unread,
Nov 25, 2009, 6:15:34 PM11/25/09
to wx-users
> I don't know/remember which platform/version do you use but to debug wx
> itself you need to build it in debug build, i.e. using --enable-debug when
> using configure. You never need to define __WXDEBUG__ manually.
>

I must be doing something wrong:

tux tb # make
g++ -Wall -g -o0 client.cpp login.cpp -o tbclient.exe `wx-config --
cxxflags` `wx-config --libs` `wx-config --enable-debug`
*** Error: Unrecognised option: '--enable-debug'
...

Vadim Zeitlin

unread,
Nov 25, 2009, 6:16:44 PM11/25/09
to wx-u...@googlegroups.com
On Wed, 25 Nov 2009 15:15:34 -0800 (PST) Daniel <danw...@gmail.com> wrote:

D> > I don't know/remember which platform/version do you use but to debug wx
D> > itself you need to build it in debug build, i.e. using --enable-debug when
D> > using configure. You never need to define __WXDEBUG__ manually.
D> >
D>
D> I must be doing something wrong:
D>
D> tux tb # make
D> g++ -Wall -g -o0 client.cpp login.cpp -o tbclient.exe `wx-config --
D> cxxflags` `wx-config --libs` `wx-config --enable-debug`
D> *** Error: Unrecognised option: '--enable-debug'

You need to specify it when building wx, not when building your
application. I.e. when you run wx configure you must pass --enable-debug to
it.

Daniel

unread,
Nov 25, 2009, 6:48:28 PM11/25/09
to wx-users
OK, I set debug on using `wx-config --debug`in my compilation.

But if I set a break point at the Execute command and then do step it
simply calls Execute but does not step into it:

Breakpoint 1, TBClientFrame::Login (this=0x1d9b150, login=@0x1e5d590,
passwd=@0x1e5d598) at client.cpp:82
82 tmpptr->Execute((wxChar*) tmp.c_str());
(gdb) s

Program received signal SIGSEGV, Segmentation fault.
0x000000000040c273 in TBClientFrame::Login (this=0x1d9b150,
login=@0x1e5d590, passwd=@0x1e5d598) at client.cpp:82
82 tmpptr->Execute((wxChar*) tmp.c_str());


How do I actually step into the Execute function?

Vadim Zeitlin

unread,
Nov 25, 2009, 6:51:20 PM11/25/09
to wx-u...@googlegroups.com
On Wed, 25 Nov 2009 15:48:28 -0800 (PST) Daniel <danw...@gmail.com> wrote:

D> OK, I set debug on using `wx-config --debug`in my compilation.
D>
D> But if I set a break point at the Execute command and then do step it
D> simply calls Execute but does not step into it:
D>
D> Breakpoint 1, TBClientFrame::Login (this=0x1d9b150, login=@0x1e5d590,
D> passwd=@0x1e5d598) at client.cpp:82
D> 82 tmpptr->Execute((wxChar*) tmp.c_str());
D> (gdb) s
D>
D> Program received signal SIGSEGV, Segmentation fault.
D> 0x000000000040c273 in TBClientFrame::Login (this=0x1d9b150,
D> login=@0x1e5d590, passwd=@0x1e5d598) at client.cpp:82
D> 82 tmpptr->Execute((wxChar*) tmp.c_str());
D>
D>
D> How do I actually step into the Execute function?

It looks like you still don't have debug information for wx somehow, it
definitely should step inside otherwise. Doesn't gdb complain about it?

On an unrelated note, this casting to wxChar* is a really bad idea. It
might be harmless here but you will definitely regret it if you take a
habit of doing it. Just call Execute(tmp) unless you have some really good
reason to not do it.

Nathan Ridge

unread,
Nov 26, 2009, 1:01:15 AM11/26/09
to wx-u...@googlegroups.com

> From: danw...@gmail.com
> To: wx-u...@googlegroups.com

I think you're misunderstanding what Vadim is saying.

You need to rebuild the entire wxWidgets libraries in debug mode,
not just your application. As in, go to your wxWidgets build directory,
invoke "configure" with the appropriate options (--enable-debug
among them), then "make".

Note that "configure" and "wx-config" are two very different scripts.
"configure" generates the makefiles for building wxWidgets; it is
something you call before building or re-building wxWidgets.
"wx-config" is something you call after wxWidgets is already built;
it simply tells you what flags you need to pass to your compiler
and linker to build your application.

Regards,
Nate.
_________________________________________________________________
Eligible CDN College & University students can upgrade to Windows 7 before Jan 3 for only $39.99. Upgrade now!
http://go.microsoft.com/?linkid=9691819

Tom Molesworth

unread,
Nov 26, 2009, 9:37:46 AM11/26/09
to wx-u...@googlegroups.com, danw...@gmail.com
Hi there,

Quick answer: your ->GetConnection() method is likely returning null, so
the segmentation fault isn't in wxwidgets code, it's due to an
uninitialised pointer. More details below:
When gdb shows a segmentation fault like this, it sounds more likely
that it didn't get as far as calling Execute - something else went wrong
first (otherwise you'd see a stack trace to the location where the
actual failure occurred - even without debugging enabled, it'd give you
the memory address). So it's more likely that tmpptr or tmp.c_str() are
invalid - maybe try the following from that breakpoint in gdb (before
the step command):

print tmpptr (should give an address)
print *tmpptr (should show the content of the tmpptr class)
print tmp (should show contents of tmp)
print tmp.c_str() (should give you the asciiz string contents)

If tmp is invalid, then the lookup for Execute will fail. If the string
is invalid, then the call to c_str() will fail.

In this case, I'm fairly sure that tmpptr is invalid. Looking at your
original code, you define the class like this:

> class TBClient : public wxTCPClient
> {
> public:
> TBClient(void) {}
> wxConnectionBase *OnMakeConnection(void)
> { return new TBConnection; }
> TBConnection *GetConnection()
> { return tb_connection; }
> protected:
> TBConnection *tb_connection;
> };
which never sets tb_connection, so will always return the uninitialised
value (which could be null or just about anything else - with maybe
slightly better odds than 1/2^64 that it'll be the actual value you wanted).

To start with, any member variable should be initialised unless you have
good reason not to do so. For a pointer like this, changing your
constructor to:

TBClient() : tb_connection(0) { }

should ensure you have either NULL or a valid pointer, which also means
you can call delete without having to check the value (you could do this
in the destructor, for example).

OnMakeConnection should set tb_connection as well as returning the
value, so that becomes:

wxConnectionBase *OnMakeConnection(void)
{
// Only allow single connection to be set, will raise an error if the connection already exists
wxASSERT(!tb_connection);
tb_connection = new TBConnection();
return tb_connection;
}


In general, your code should be checking for null pointers rather than
assuming everything returns a valid result - if your code still reads as
follows:

> wxString tmp = wxT("Hello");
> tmpptr = tb_client->GetConnection();
> wxMessageBox(wxT("Ready to execute."), wxT(""));
> tmpptr->Execute((wxChar*) tmp.c_str());

then you should think about adding wxASSERT(tmpptr) after the GetConnection() line if you're not going to add proper error handling (such as retrying the connection or reporting the error message). Also, Execute() should accept const wxString so the cast + c_str() doesn't seem necessary here.


Tom

Daniel

unread,
Nov 26, 2009, 4:43:56 PM11/26/09
to wx-users
Thanks for your help. You were right about the null pointer. After I
set it to null on creation, it is still null after MakeConnection. So
I guess that means my client program is still not connecting, despite
the fact that the servers OnAcceptConnection is invoked after the
MakeConnection call on the client:

wxConnectionBase *TBServer::OnAcceptConnection(const wxString& topic)
{
wxLogMessage(_T("OnAcceptConnection(\"%s\")"), topic.c_str());

if (topic == wxT(TCP_TOPIC))
{
tb_connection = new TBConnection();
//wxGetApp().GetFrame()->Enable();
wxLogMessage(wxT("Connection accepted"));
return tb_connection;
}
// unknown topic
return NULL;
}

Strange eh? Any ideas as to the problem? (Although the original
problem, as in the title is solved now. )

Daniel

unread,
Nov 29, 2009, 5:17:21 PM11/29/09
to wx-users
I changed OnMakeConnection as given by Tom Molesworth in the above
post, and all was well and good the client successfully connected and
the server received the message.
Reply all
Reply to author
Forward
0 new messages