2010年6月16日星期三

两个关于char*的bug (QDebug, itoa)

100_2995

此图和本文无关。图为德国埃森的华纳影城的街景(4年前拍的,昨天在整理照片发现的),我很喜欢这张,海绵宝宝。要了解正文请继续阅读。

我今天刚刚发现的我写的两个愚蠢的bug,都和char*有关。
这个两个愚蠢的bug都是因为我自己对一些函数的不正确,过于简单的理解造成的。
要警惕啊,随手写下来,记录一下。

[1]
在使用Qt的时候,我非常喜欢使用QDebug。
可以任意输出什么东西。
可是没有想到,QDebug也会给我造成bug,使测试崩溃。
例如我使用:
QDebug & QDebug::operator<< ( const char * s )
Writes the '\0'-terminated string, s, to the stream and returns a reference to the stream.

rmsg.Answer是一个char*
qDebug() << " Answer:" << rmsg.Answer;

就会得到类似的输出
First-chance exception at 0x670a7fb9 (QtCored4.dll) in **.exe: 0xC0000005: Access violation reading location 0x0000000f.
Unhandled exception at 0x670a7fb9 (QtCored4.dll) in **.exe: 0xC0000005: Access violation reading location 0x0000000f.

发现
Qt的qstring.cpp

QString::Data *QString::fromLatin1_helper(const char *str, int size)
{
    Data *d;
    if (!str) {
        d = &shared_null;
        d->ref.ref();
    } else if (size == 0 || (!*str && size < 0)) {    //程序崩溃在这里
    } else {
        if (size < 0)
            size = qstrlen(str);
        d = static_cast<Data *>(qMalloc(sizeof(Data) + size * sizeof(QChar)));
        d->ref = 1;
        d->alloc = d->size = size;
        d->clean = d->asciiCache = d->simpletext = d->righttoleft = d->capacity = 0;
        d->data = d->array;
        ushort *i = d->data;
        d->array[size] = '\0';
        while (size--)
           *i++ = (uchar)*str++;
    }
    return d;
}

这到底是什么原因呢?

因为我给了错误的指针。

如果得到比较怪异的指针,qDebug()无法正确转换成QString或者(whatever进行一些有关于QString的处理)进行输出的时候就会产生这样的错误。

[2]
现在来谈谈第二个关于char*的bug。

/***
*xtoa.c - convert integers/longs to ASCII string
*
*       Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
*       The module has code to convert integers/longs to ASCII strings.
***/

常常使用<stdlib.h>里的函数itoa进行int 到char*的转换
char * itoa ( int value, char * str, int base );

如果这样写
/* use the itoa() to convert int to char* */
int id = 10;
char *id_char;
itoa (id, id_char, 10);

就会出错,然后如果使用Visual Studio进行debug就会跳到xtoa.c里。

/***
*xtoa.c - convert integers/longs to ASCII string
*
*       Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
*       The module has code to convert integers/longs to ASCII strings.
***/

为什么呢,还是因为没有定好char*的具体范围。
大概是这样的。
该怎么做呢,其实很简单。
只需如下定义char*就行了。
char id_char[3];

/* use the itoa() to convert int to char* */
int id = 10;
char id_char[3];
itoa (id, id_char, 10);

没有评论: