We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 5226 - SDL_BlitSurface refcount goes negative
Summary: SDL_BlitSurface refcount goes negative
Status: RESOLVED FIXED
Alias: None
Product: SDL
Classification: Unclassified
Component: render (show other bugs)
Version: 2.0.10
Hardware: All All
: P2 normal
Assignee: Sam Lantinga
QA Contact: Sam Lantinga
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-07-09 13:17 UTC by Dave Lawrence
Modified: 2020-10-03 02:32 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Dave Lawrence 2020-07-09 13:17:19 UTC
Is it expected behaviour for

SDL_BlitSurface(source, 0, target, 0);

to increment the refcount of target? Just because I’ve blitted source to target does that necessarily mean that target ‘has a reference’ to source?

(As I call FreeSurface on my source~s the refcount of target does decrease)

Here is a simple demonstration


#include "SDL.h"

void test(int x)
{
    SDL_Surface *image1 = SDL_CreateRGBSurface(0, 100,100, 32, 0, 0, 0, 0);
    SDL_Surface *image2 = SDL_CreateRGBSurface(0, 100,100, 32, 0, 0, 0, 0);
    printf("%d load: image1 %d image2 %d\n", x, image1->refcount, image2->refcount);
    SDL_BlitSurface(image1, 0, image2, 0);
    printf("%d blit: image1 %d image2 %d\n", x, image1->refcount, image2->refcount);
    if (x == 0)
    {
        SDL_FreeSurface(image1);
        SDL_FreeSurface(image2);
    }
    else
    {
        SDL_FreeSurface(image2);
        SDL_FreeSurface(image1);
    }
    printf("%d free: image1 %d image2 %d\n", x, image1->refcount, image2->refcount);
}

int main(int argc, char* argv[])
{
    test(0);
    test(1);
}

Compile with

g++ -o sdleg3 sdleg3.c -LSDL2 -I/usr/include/SDL2 -lSDL2

Output is

0 load: image1 1 image2 1
0 blit: image1 1 image2 2
0 free: image1 0 image2 0
1 load: image1 1 image2 1
1 blit: image1 1 image2 2
1 free: image1 0 image2 -1

So deleting the target surface first leads to a refcount of -1
Comment 1 Sylvain 2020-07-21 13:51:51 UTC
You cannot look any-more at the surface after freeing it (eg after SDL_FreeSurface()). this is an invalid memory access.

the instruction "printf("%d free: ..." is wrong.

Resolved as invalid
Comment 2 Dave Lawrence 2020-07-21 14:04:24 UTC
Hi,
OK, understood it is invalid after the free()
but why is it incremented after the blit?
thanks,
Comment 3 Sylvain 2020-07-21 18:19:03 UTC
Some data is cached in the destination surface, when when blitting from 1 src to 1 dst. (what is computed in SDL_MapSurface()). the data remains in src surface, and we keep a reference on it so it doesn't get deleted.

see SDL_pixels.c:

  1046         /* Keep a reference to this surface so it doesn't get deleted
  1047            while we're still pointing at it.
  1048 
  1049            A better method would be for the destination surface to keep
  1050            track of surfaces that are mapped to it and automatically 
  1051            invalidate them when it is freed, but this will do for now.

https://hg.libsdl.org/SDL/file/84b67c1312c6/src/video/SDL_pixels.c#l1046

Fixed blit mapping problem when surfaces are freed and then newly allocated at the same address.
https://hg.libsdl.org/SDL/rev/84b67c1312c6
Comment 4 Sylvain 2020-10-02 08:52:33 UTC
NB, previous comment was fixed in:

https://hg.libsdl.org/SDL/rev/53e29c306f45
https://hg.libsdl.org/SDL/rev/1b1fae168557
Comment 5 Sam Lantinga 2020-10-03 02:32:50 UTC
This is fixed, thanks!