List:MySQL++« Previous MessageNext Message »
From:Kristofer Spinka Date:November 17 2005 10:27pm
Subject:Query class derived from std::ostream constructor issue
View as plain text  
Hi, I've noticed a serious bug that was introduced in 
MySQL++ v2.0.0 when the Query class was changed to derive 
from std::ostream.

Per the C++ standard, regardless of the order of 
statements in a constructor's initialization list, base 
classes are initialized before the members of the current 
class are.

===
So in query.h:188:
     Query(Connection* c, bool te = true) :
     std::ostream(&sbuffer_),
     OptionalExceptions(te),
     Lockable(false),
     def(this),
     conn_(c),
     success_(false)
     {
         success_ = true;
     }

     ... line: 694
     /// \brief String buffer for storing assembled query
     std::stringbuf sbuffer_;
===

The std::stringbuf “sbuffer_” is not yet initialized when 
it is passed into the std::ostream constructor.

If you build with g++, you can get away with this (not 
sure if it leads to any memory corruption), but with Sun 
Studio 11 compilers (and other compilers), for example, 
you will incur a memory access fault.

The simple solution is to make the sbuffer_ member a 
pointer and allocate it in Connection::query() passing the 
newly created object as a parameter to the Query() 
constructor and clean it up in Query’s destructor.

I’ve attached an example of the changes.

   /kristofer

--- ../../../mysql++-2.0.6/lib/connection.cpp	Mon Sep 26 10:21:49 2005
+++ connection.cpp	Thu Nov 17 13:36:57 2005
@@ -200,7 +200,8 @@
 bool
 Connection::create_db(const std::string& db)
 {
-	Query q(this, throw_exceptions());
+	std::stringbuf *sb = new std::stringbuf;
+	Query q(this, sb, throw_exceptions());
 	return q.exec("CREATE DATABASE " + db);
 }
 
@@ -208,7 +209,8 @@
 bool
 Connection::drop_db(const std::string& db)
 {
-	Query q(this, throw_exceptions());
+	std::stringbuf *sb = new std::stringbuf;
+	Query q(this, sb, throw_exceptions());
 	return q.exec("DROP DATABASE " + db);
 }
 
@@ -272,7 +274,8 @@
 Query
 Connection::query()
 {
-	return Query(this, throw_exceptions());
+	std::stringbuf *sb = new std::stringbuf;
+	return Query(this, sb, throw_exceptions());
 }
 
 
--- ../../../mysql++-2.0.6/lib/query.cpp	Mon Sep 26 10:21:49 2005
+++ query.cpp	Thu Nov 17 13:32:32 2005
@@ -31,7 +31,7 @@
 namespace mysqlpp {
 
 Query::Query(const Query& q) :
-std::ostream(&sbuffer_),	
+std::ostream(sbuffer_),
 OptionalExceptions(q.exceptions()),
 Lockable(q.locked()),
 def(q.def),
@@ -291,9 +291,9 @@
 char* Query::preview_char()
 {
 	*this << std::ends;
-	size_t length = sbuffer_.str().size();
+	size_t length = sbuffer_->str().size();
 	char* s = new char[length + 1];
-	strcpy(s, sbuffer_.str().c_str());
+	strcpy(s, sbuffer_->str().c_str());
 	return s;
 }
 
@@ -300,7 +300,7 @@
 
 void Query::proc(SQLQueryParms& p)
 {
-	sbuffer_.str("");
+	sbuffer_->str("");
 
 	char num;
 	SQLString* ss;
@@ -333,7 +333,7 @@
 {
 	seekp(0);
 	clear();
-	sbuffer_.str("");
+	sbuffer_->str("");
 
 	parse_elems_.clear();
 	def.clear();
@@ -452,7 +452,7 @@
 
 	*this << std::ends;
 
-	return sbuffer_.str();
+	return sbuffer_->str();
 }
 
 
--- ../../../mysql++-2.0.6/lib/query.h	Thu Nov 17 17:13:51 2005
+++ query.h	Thu Nov 17 17:14:08 2005
@@ -185,17 +185,23 @@
 	///
 	/// \param c connection the finished query should be sent out on
 	/// \param te if true, throw exceptions on errors
-	Query(Connection* c, bool te = true) :
-	std::ostream(&sbuffer_),
+	Query(Connection* c, std::stringbuf *sb, bool te = true) :
+	std::ostream(sb),
 	OptionalExceptions(te),
 	Lockable(false),
 	def(this),
 	conn_(c),
-	success_(false)
+	success_(false),
+	sbuffer_(sb)
 	{
 		success_ = true;
 	}
 
+	~Query()
+	{
+		delete sbuffer_;
+	}
+
 	/// \brief Create a new query object as a copy of another.
 	///
 	/// This is \b not a traditional copy ctor!  Its only purpose is to
@@ -692,7 +698,7 @@
 	std::map<std::string, short int> parsed_nums_;
 
 	/// \brief String buffer for storing assembled query
-	std::stringbuf sbuffer_;
+	std::stringbuf *sbuffer_;
 
 	//// Internal support functions
 	my_ulonglong affected_rows() const;
Thread
Query class derived from std::ostream constructor issueKristofer Spinka17 Nov
  • Re: Query class derived from std::ostream constructor issueChris Frey21 Nov
    • Re: Query class derived from std::ostream constructor issueChris Frey21 Nov
      • Re: Query class derived from std::ostream constructor issueWarren Young23 Nov
        • Re: Query class derived from std::ostream constructor issueChris Frey23 Nov
Re: Query class derived from std::ostream constructor issueKristofer Spinka22 Nov