A common assumption made by novice programmers is that all variables are set to a known value, such as zero, when they are declared.
Therefore, whatever contents of that memory at the time will appear as initial values of the variables which occupy those addresses.
The function register_student leaks memory contents because it fails to fully initialize the members of struct student new_student.
Hence after memcpy()'ing the resulted struct to output,[2] we leak some stack memory to the caller.
Exploiting an uninitialized variable in a way to force the software to leak a pointer from its address space can be used to bypass ASLR.
Some languages assist this task by offering constructs to handle the initializedness of variables; for example, C# has a special flavour of call-by-reference parameters to subroutines (specified as out instead of the usual ref), asserting that the variable is allowed to be uninitialized on entry but will be initialized afterwards.