renderer/paint: fixed a mismatched reference count.

This correction ensures a consistent use of 'ref' and 'unref' for paints to release memory properly.
The memory leak occurred when a picture was not pushed to a valid canvas.

This issue was reported by the unit-test memory sanitizer.
This commit is contained in:
Hermet Park 2023-09-25 23:39:28 +09:00 committed by Hermet Park
parent 2fb0cc8309
commit 1819fed033
8 changed files with 17 additions and 8 deletions

View file

@ -304,6 +304,7 @@ unique_ptr<Paint> LottieLoader::paint()
{
this->done();
if (!comp) return nullptr;
comp->initiated = true;
return cast<Paint>(comp->scene);
}

View file

@ -158,6 +158,8 @@ int32_t LottieLayer::remap(int32_t frameNo)
LottieComposition::~LottieComposition()
{
if (!initiated) delete(scene);
delete(root);
free(version);
free(name);

View file

@ -585,6 +585,7 @@ struct LottieComposition
float frameRate;
Array<LottieObject*> assets;
Array<LottieInterpolator*> interpolators;
bool initiated = false;
};
#endif //_TVG_LOTTIE_MODEL_H_

View file

@ -36,12 +36,12 @@ struct Animation::Impl
Impl()
{
picture = Picture::gen().release();
static_cast<Paint*>(picture)->pImpl->ref();
PP(picture)->ref();
}
~Impl()
{
if (static_cast<Paint*>(picture)->pImpl->unref() == 0) {
if (PP(picture)->unref() == 0) {
delete(picture);
}
}

View file

@ -53,6 +53,7 @@ struct Canvas::Impl
auto p = paint.release();
if (!p) return Result::MemoryCorruption;
PP(p)->ref();
paints.push_back(p);
return update(p, true);
@ -66,8 +67,9 @@ struct Canvas::Impl
//Free paints
if (free) {
for (auto paint : paints) {
if (paint->pImpl->dispose(*renderer)) {
if (paint->pImpl->unref() == 0) delete(paint);
P(paint)->unref();
if (paint->pImpl->dispose(*renderer) && P(paint)->refCnt == 0) {
delete(paint);
}
}
paints.clear();

View file

@ -68,7 +68,7 @@ namespace tvg
uint8_t ctxFlag = ContextFlag::Invalid;
uint8_t id;
uint8_t opacity = 255;
uint8_t refCnt = 1;
uint8_t refCnt = 0;
~Impl()
{

View file

@ -55,6 +55,7 @@ Result Scene::push(unique_ptr<Paint> paint) noexcept
{
auto p = paint.release();
if (!p) return Result::MemoryCorruption;
PP(p)->ref();
pImpl->paints.push_back(p);
return Result::Success;

View file

@ -220,7 +220,9 @@ struct Scene::Impl
auto dup = ret.get()->pImpl;
for (auto paint : paints) {
dup->paints.push_back(paint->duplicate());
auto cdup = paint->duplicate();
P(cdup)->ref();
dup->paints.push_back(cdup);
}
return ret.release();
@ -231,8 +233,8 @@ struct Scene::Impl
auto dispose = renderer ? true : false;
for (auto paint : paints) {
if (dispose) free &= paint->pImpl->dispose(*renderer);
if (free) delete(paint);
if (dispose) free &= P(paint)->dispose(*renderer);
if (P(paint)->unref() == 0 && free) delete(paint);
}
paints.clear();
renderer = nullptr;