You don’t need to have a list of surfaces, since there will only be one (1) surface per created window. All you need is a single SDL_Surface pointer, which you set to the window surface by calling SDL_GetWindowSurface().
Just like the documentation says, the surface will be invalidated if/when the window is resized. This means that, if you have assigned an SDL_Surface to the window surface earlier (i.e by calling SDL_GetWindowSurface()), you’ll need to call the same function again to assign your SDL_Surface to a valid window surface.
So somewhere in your code, probably in your event loop, at the point where a window resize event has happened, do whatever you need to do to handle the window resize and then finally call pMyWindowSurface = SDL_GetWindowSurface(pMyWindow); to make your surface valid again.
My concern is about the pointer SDL_Surface* obtained. “Invalid” might mean that it must not be used any longer by any of the surface functions, as all fields of the structure are no longer valid, in particular the pointer to the pixel data refers to memory that is no longer allocated.
Also the pointer obtained by SDL_GetWindowSurface() does no longer refer to valid storage, i.e. a dangling pointer might be a result of resizing a window. (Which is the same obtaining a surface, e.g. by SDL_CreateRGBSurface, copying the pointer, then using SDL_FreeSurface with one of the copies, which invalidates all the other.) Is that correct?
Assuming that SDL_GetWindowSurface() is not an expensive operation (because it just delivers a copy of the pointer to the SDL_Surface allocated for the window), this pointer should only be used locally in a short context and freshly obtained whenever the window has to be modified, but better not saved in global variable or a structure.
When writing a language binding, this means that the surface obtained this way should not be exposed to the host language, at least in the final version.
To be honest, I haven’t really used the SDL_GetWindowSurface() function much. The documentation sadly doesn’t say much about the function either and what actually happens to the surface pointer when a window resize occur.
Hopefully someone with better knowledge of the function can tell you more of the actual surface and its validity. Sorry to not being able to help more.
Some tutorials use it in their first examples, probably because its fairly simple and requires surfaces only.
Using Renderers seems to be the more advisable way then, although it requires some additional steps.
SDL_GetWindowSurfacemayre-create the surface, which dependent on the “backend” can be a super expensive operation, especially in the context of a game loop, so in general you want to be in control of when that happens. You might not want to do it continuously while the window is being resized, instead have some delay after the last resize event before handling it, for example.
If you are allowing the window to be resized(which you need to do explicitly), you will need to handle the resize events anyway in most cases, so tossing this call in there is not a big deal.
Regarding dangling pointers there shouldn’t be any, as you can see in the source I linked above, the surface is destroyed in the same function. Until that point, if you try to pass it to any of the API functions that accept a surface, you should just get an error.
If you don’t want to expose this to the users of a language binding or a wrapper library, I recommend at least having a consistent strategy of handling this based on resize events, and not just “any one of your window surface accesses might randomly take a huge amount of time”.