Yes, you’re correct - every SDL_Surface and SDL_Texture created by the developer should be destroyed with corresponding SDL_FreeSurface/SDL_DestroyTexture function call. Not following that will result in memory leak(s).
My GPU has a limited amount of memory, If I keep allocating textures, without destroying them, I would expect the program crashes for lack of resources. In this case GPU memory.
User space programs don’t have any control over what is actually using GPU memory. If you require more storage than your hardware has the driver will happily stream unused textures out of the GPU into system RAM so it can load textures it will actually need.
No, you should definitely avoid using more than you have. It is extremely slow to stream data back and forth from the GPU and you want to avoid making things slow to a crawl (among other things). Allocating textures without freeing them is a resource leak that serves no good. It leaks more than GPU memory anyway. Eventually something would give, but that depends on implementation details and shouldn’t matter if you have a well behaved program.