PDA

View Full Version : Debug macros in 64bit systems



mcostalba
2nd December 2006, 07:07
Hi all,

I use the following debug macro to quicly check variables values in code of interest:

#define dbs(x) qDebug(QVariant(x).toString().latin1())

I can write something like


dbs(5);
dbs("5");

int num = 5;
dbs(num);

QString str("5");
dbs(str);

and everything works as expected.

I have a problem with container's sizes that are size_t types.

As example:


QValueVector<int> v;
v.append(5);

dbs(v.count()); // gives an error on 64bit systems

This is because size_t is an unsigned int 64 bits long and cannot be auto converted by compiler to int or uint types that are 32 bits and are the only constructors defined by QVariant for integral types.

How can do my macro work as expected? there exsist another way to write a macro with the same results.

I searched on the net with no results, so here I am asking for an help.

Thanks
Marco

wysota
2nd December 2006, 08:09
Why not use qDebug class instead?


#include <QtDebug>
//...
qDebug() << v.count();

mcostalba
2nd December 2006, 09:16
int num = 5;
qDebug() << num;

/usr/lib/qt3//include/qglobal.h:975: error: too few arguments to function ‘void qDebug(const char*, ...)’git_startup.cpp:529: error: at this point in file

Thanks
Marco

mcostalba
2nd December 2006, 09:35
BTW I have qt 3.3.6 installed.

wysota
2nd December 2006, 13:34
BTW I have qt 3.3.6 installed.
Ah, sorry, I missed that :)

There is a QVariant constructor that takes a Q_LLONG argument, I think it should work for you. Try using
dbs((Q_LLONG)v.count());

Casting the value to uint should work as well, especially that QValueVector::count() should return an uint all by itself... If you have a 64b architecture then uint should be 64 bits wide as well. Are you sure your code is correct?

mcostalba
2nd December 2006, 14:26
Thanks, currently I use

dbs((int)v.count());

and it works....but it's ugly and easy to forget to cast. The problem is I have a 32bit box and I don't experience the compile error when writing

dbs(v.count());

but my tool is publicy released to wider audience, with any kind of system. BTW the compile error was found by an user and reported to me. So I really would like to have a dbs(x) macro that prints _anything_ 'x' is without always remember to cast to int/uint the size_t values.

Thanks
Marco

P.S: I cannot subclass QVariant because key 'd' internal variable is private. I was thinking at template specialization, something like:

template<typename T>class MyVariant {
public:
MyVariant(T x) : v(x){}
QString toString() { return v.toString(); }
private:
QVariant v;
};
template<>class MyVariant<size_t> {
public:
MyVariant(size_t x) : v((uint)x){}
QString toString() { return v.toString(); }
private:
QVariant v;
};


But in this case I need to pass the type when instancing the template or as macro parameter.


Any ideas?? :)

Thanks
Marco

wysota
2nd December 2006, 15:42
Maybe you should implement a series of (template) functions that would do debugging? You could handle specific types yourself and leave all the others to the template function.

For instance:


template<class T> void myDbg(T a){
qDebug(a);
}

void myDbg(size_t a){
qDebug((int)a);
}

void myDbg(QString s){
qDebug("%s", s.latin1());
}

mcostalba
2nd December 2006, 18:18
A great idea. Thanks!

It works. I updated my common header with:

template<typename T> const QString _valueOf(const T& x) { return QVariant(x).toString(); }
inline const QString _valueOf(const QString& x) { return x; }
inline const QString _valueOf(size_t x) { return QString::number((uint)x); }

// some debug macros
#define dbg(x) qDebug(#x " is <%s>", _valueOf(x).latin1())
#define dbs(x) qDebug(_valueOf(x))
#define dbp(s, x) qDebug(QString(s).arg(_valueOf(x)))


Thanks again
Marco

wysota
2nd December 2006, 20:16
I suggest you also do something like this to easily disable debugging:


#ifndef NO_DISPLAY_DEBUG
# define dbg(x) qDebug(#x " is <%s>", _valueOf(x).latin1())
# define dbs(x) qDebug(_valueOf(x))
# define dbp(s, x) qDebug(QString(s).arg(_valueOf(x)))
#else
# define dbg(x)
# define dbs(x)
# define dbp(s, x)
#endif

I'm not sure about the syntax of the second section, so be prepared for compile errors :)