SDK Ver. Qt 4.8.6


현상)

QByteArray 객체를 기본 생성자로 선언하고 reserve 로 크기를 정하고 복사를 하니 size가 제대로 나오지 않았다.

resize 로는 정상 동작 하였다.


const char *cba = "great!";

QByteArray ba;
ba.reserve(10);

memset(ba.data(), 0, 10);
mempcpy(ba.data(), (const char*)cba, 6);

qDebug() << "ba = " << ba.data();

qDebug("ba size[%d] ba isNull[%d]", ba.size(), ba.isNull());


원인)

size가 제대로 동작하지 않은 이유..

QByteArray 객체를 기본 생성자로 생성하면 QByteArray 내부 private 변수인 d (구조체 포인터) 값을 shared_null 의 주소 값으로 설정한다. 이후 reserve 를 호출하면 내부적으로 QByteArray의 realloc을 호출하게 되는데 여기서 문제가 발생한다.


realloc 내부를 보면 아래와 같이 x라는 변수에 메모리를 할당 받고 d가 x를 가리키게 한다.


void QByteArray::realloc(int alloc)
{
    if (d->ref != 1 || d->data != d->array) {
        Data *x = static_cast<Data *>(qMalloc(sizeof(Data) + alloc));
        Q_CHECK_PTR(x);
        x->size = qMin(alloc, d->size);
        ::memcpy(x->array, d->data, x->size);
        x->array[x->size] = '\0';
        x->ref = 1;
        x->alloc = alloc;
        x->data = x->array;
        if (!d->ref.deref())
            qFree(d);
        d = x;
    } else {
        Data *x = static_cast<Data *>(qRealloc(d, sizeof(Data) + alloc));
        Q_CHECK_PTR(x);
        x->alloc = alloc;
        x->data = x->array;
        d = x;
    }

}


d->size 값과 alloc 값 중 작은 값을 size로 넣게 되는데, 이 인자는 reserve 에서 인자로 넘어온 값이 realloc에서도 인자로 넘어가고 메모리를 할당 받게 된다.

하지만 d->size 값이 위의 코드로 인해 d->size 값 (0) 이 다시 기록되고 그 결과 size 함수를 호출하면 0이 나오는 기이한 현상이 발생한다.


이 예로 사용 된 QByteArray 객체는 size() 는 0이지만 data() 메서드로 호출해 보면 값이 들어 있다.



결론)

내가 아직 개념을 잘못 알고 있는 것이 아닐까 생각이 든다.

reserve 는 API 레퍼런스에 나와 있듯이 성능 튜닝 용도로만 사용하거나 사용 안하는 것이 좋겠다.


참고)

reserve는 할당된 크기보다 인자로 넘긴 크기가 클 경우에만 realloc 하는 인라인 함수로 구현. (5.x 에서는 좀 다름)

resize는 현재 크기보다 인자로 넘긴 크기가 클 경우 뿐 아니라 작은 경우에도 realloc을 한다.


'QT' 카테고리의 다른 글

undefined reference to 'vtable for...'  (0) 2016.05.19
반투명 그릴 때 배경 잔상 문제  (0) 2016.05.11
libwinpthread 가 계속 동적 빌드만 될 때  (0) 2016.04.28
디버깅 매크로  (0) 2016.04.19
QT static build with mingw32  (0) 2015.09.17
Posted by 독뽀
,