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 |