| Summary: | SDL_BlitSurface refcount goes negative | ||
|---|---|---|---|
| Product: | SDL | Reporter: | Dave Lawrence <dl> |
| Component: | render | Assignee: | Sam Lantinga <slouken> |
| Status: | RESOLVED FIXED | QA Contact: | Sam Lantinga <slouken> |
| Severity: | normal | ||
| Priority: | P2 | CC: | sylvain.becker |
| Version: | 2.0.10 | ||
| Hardware: | All | ||
| OS: | All | ||
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
Hi, OK, understood it is invalid after the free() but why is it incremented after the blit? thanks, 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 NB, previous comment was fixed in: https://hg.libsdl.org/SDL/rev/53e29c306f45 https://hg.libsdl.org/SDL/rev/1b1fae168557 This is fixed, thanks! |
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