On 03/18/2011 07:30 PM, Warren Young wrote:
> On Mar 18, 2011, at 8:59 AM, Florian Feldbauer wrote:
>> I have attached the modified source of tquery1.cpp.
> Okay, I've figured out what's going on. I've been doing my tests against the svn
> version of MySQL++, not the 3.1.0 released version. This bug was squished in svn back in
> The only thing holding me back from releasing 3.1.1 is that I want to fix the ABI
> breakage created by 3.1.0, reverting it to the 3.0.9 ABI. If someone wants to give me a
> patch for this, 3.1.1 should shortly follow.
As shown in the compatibility report for mysql++ 3.0.9 and 3.1.0
versions [1-2], there are 4 problems with ABI/binary compatibility:
1. class ConnectionPool: exchange() and safe_grab() virtual functions
were added at the middle position of v-table,
2. class Comparable: removed _ZN10ComparableIN7mysqlpp4DateEED0Ev
destructor from libmysqlpp.so,
3. class DBDriver: increased the size from 1012 to 1056 bytes because
of added pending_options_ and error_message_ fields,
4. method DBDriver::set_option(): changed return value from
std::string (class) to bool (intrinsic).
1) Lets consider the first problem. The ConnectionPool class is the leaf
class (has no derived classes in libmysqlpp) with the default/copied
constructor. This constructor was copied by old clients and will
generate old v-table layout. The problem is that new library expects a
new layout instead to call pure-virtual functions provided by the
client. So, moving both new virtual functions to the end of class
declaration after all old virtual functions will restore the positions
of old virtual functions. However, added virtual functions still will
not be presented in the old v-table generated by copied default
constructor. So, in order to not to crash old clients, it should not be
possible to call these functions through the calling of any symbols in
the old library, i.e. you should call new symbols from the new symbols
only. And it's, fortunately, true for mysql++ 3.1.0:
$> cd sources-3.1.0 && find . -name "*.cpp"| xargs grep
So, the only thing you need is to move both functions to the end of the
2) The second problem seems to be a false positive, because it is not
possible to import this symbol from the libmysqlpp.so. The Comparable
class has only default/copied constructor and therefore old clients will
call an old copy of the removed symbol pointed by the old v-table copied
by the constructor. The abi-compliance-checker tool will be improved in
the future versions to not to report this false alarm.
3) The DBDriver class has an exported constructor and size of this class
has been increased. Old size of this class will be hard-coded in the
clients at the compile time and call of the new-version constructor will
break the memory of neighboring objects on the stack or heap.
The layout of old DBDriver class:
// 4 bytes for v-table pointer
MYSQL mysql_; // 964 bytes
bool is_connected_; // 1 byte
// 3 bytes internal padding
OptionList applied_options_; // 40 bytes
// no tail padding
So, unfortunately, there is no place for pointer to hide added fields
and the only way to move new fields away from the class is to create a
derived class and move new fields to it or completely revert this change.
I recommend you to add reserved fields and virtual functions to the end
of classes on the next ABI break in 4.0.
4) The return value of class type is passed through the first hidden
parameter on the calling stack, unlike the intrinsic values, which are
passed through the registers. So, there are two options here:
- Change return value to a class derived from std::string with the
"operator bool()" and "operator std::string()". This should be both
binary and source backward-compatible,
- Revert this change.
Department for Operating Systems at ISPRAS