So I guess that in this case, as the pointer that has been allocated resides in the module rather than in the 'initialize' subroutine, it stays allocated until explicitly deallocated just like an allocatable array would if held in the module.
I might be missing something here - but the "struct" fortran pointer (it is not an allocatable) being at module scope is not relevant - you could (should? see below) have it as a local variable of each subroutine and you would get the same behaviour. I think the only reason its been put at module scope here is that it saves a bit of typing.
I'd prefer "type(pass), pointer :: struct" local to each routine simply because that's the appropriate scope for the lifetime of the information that's associated with that variable. I also strongly suspect a module scope variable would have issues if this code was ever used in a multi-threaded situation, without additional code, but I don't play in that park.
Each time you call allocate on a pointer, you get a new object, in new storage. If you want to lose/leak memory, there's nothing stopping you. This is different to objects with the allocatable attribute. There's no automatic clean-up/deallocate for pointers either - the programmer needs to look after that (though I think a vendor could offer this as an extension?). The analogy with c++ is a pointer to an object allocated with new and then nuked with delete.
So normally this sort of setup would have an uninitialise/delete/destruct/free/release function that calls DEALLOCATE. For every time you "C" client code calls initialise, it must eventually call this cleanup function or the allocated object will sit around until the program terminates.
The attached might be of interest. It is not necessarily compilable/runable, but hopefully still useful. Interested in any alternative approaches you might have.
Edit: to fix file attachment problem.