[C++-sig] Segfaults in Pure Virtual Functions in Extension Module

Michael Owens owensmk at earthlink.net
Sun May 19 19:26:10 CEST 2002


I am having problems in a Python class called Session which holds a pointer
to an abstract C++ class (session --- little 's') which represents a generic 
connection to a database. The constructor will instantiate a derived session 
class (implementing a specific a database connection) call its connect() 
function, and assign the pointer to the p_session member of Session. It 
segfaults on connect() within Session's constructor. Now I know that 
session::connect() works fine as I have tested and debugged it in a regular 
C++ program.

Here are the relevent functions to create Session in the module (sdbc.cc):

static PyMethodDef sdbc_functions[] = 
{
	{ "session", NewSession, METH_VARARGS},
	{ "join", NewJoin, METH_VARARGS},
	{ NULL, NULL }
};

extern "C" void initsdbc()
{
	Py_InitModule("sdbc", sdbc_functions);
}

// Create a new Session object
PyObject* NewSession(PyObject *self, PyObject *args)
{
	const char* driver_name;
	const char* host_name;
	const char* user_name;
	const char* password;
	const char* database;

	if(!PyArg_ParseTuple(args,"sssss:Session",
						 &driver_name,
						 &host_name,
						 &user_name,
						 &password,
						 &database))
	{
		return NULL;
	}

	// Constructor will be instantiate a session object using these arguments
	return new Session(driver_name, host_name, user_name, password, database);
}



-------------------------------------------------------------------
Here is Session's declaration (from Session.h):
-------------------------------------------------------------------

// Session is an abstract C++ class representing a generic database session.
class session;

/** This class wraps the join C++ class.*/
class Session: public PyObject
{
  public:

	/** Default Constructor -- nothing special.*/
	Session( const char* dn,
			 const char* hn,
			 const char* un,
			 const char* pw,
			 const char* db );

	~Session();

	/** Python specific interfaces */
	static void dealloc(PyObject *obj);
	static PyObject *getattr(PyObject *obj, char *name);
	static int setattr(PyObject *obj, char *name, PyObject *value);
	
	static struct memberlist memberlist[];
	static PyMethodDef methodlist[];

	const char* driver_name;
	const char* host_name;
	const char* user_name;
	const char* password;
	const char* database;
	session* p_session;
}; 

-------------------------------------------------------------------
The constructor is as follows, Here is where the segfault occurs 
p_s->connect();
-------------------------------------------------------------------

Session::Session(const char* dn,
				 const char* hn,
				 const char* un,
				 const char* pw,
				 const char* db )
{
	driver_name = strdup(dn);
	host_name = strdup(hn);
	user_name = strdup(un);
	password = strdup(pw);
	database = strdup(db);

	// Instantiate a derived session class --- specific to sqlite_database.
	sqlite_session* p_s = new sqlite_session("db");


	// SEGFAULT here:
	if (p_s->connect() == false)
	{
		printf("Failed to connect to database: Error=%s\n", p_session->error());
	}
	else
	{
		printf("Connected to database.\n");
	}

	// Assign to base class pointer.
	p_session = p_s;

	ob_type = &Session_Type;

	_Py_NewReference(this);
}

Session::~Session()
{
	free((void*)driver_name);
	free((void*)host_name);
	free((void*)user_name);
	free((void*)password);
	free((void*)database);

	delete p_session;
}


-------------------------------------------------------------------
Here is Session's  memberlist and method list(Session.cc)
-------------------------------------------------------------------

#define OFF(x) offsetof(Session, x)

struct memberlist Session::memberlist[] =
{
	{"driver_name", T_STRING, OFF(driver_name)},
	{"host_name",   T_STRING, OFF(host_name)},
	{"user_name",   T_STRING, OFF(user_name)},
	{"password",    T_STRING, OFF(password)},
	{"database",    T_STRING, OFF(database)},
	{NULL}
};

PyMethodDef Session::methodlist[] =
{
	{ NULL, NULL}
};

-------------------------------------------------------------------
The python code is as follows:
-------------------------------------------------------------------

#!/usr/bin/python

import sdbc

s = sdbc.session("SQLite", "localhost", "root", "", "db")

# Crash. If I don't embed session within Session, there is not problem. It all
# pivots around the presence of session with Session and calling connect(). If 
I don't call connect, or call one of session's non-virtual function, there is 
no segfault here.
j = sdbc.join(s)




> Please post the code you used to expose A and B to Python, and a snippet of
> Python code which causes the crash.
>
> Thanks,
> Dave






More information about the Cplusplus-sig mailing list