Nella modalità Debug vengono definite una serie di opzioni del compilatore che consentono al debugger di seguire sul sorgente l'esecuzione del programma; inoltre sono abilitate un'altra serie di opzioni, come modifica e continuazione e i vari runtime checks, e l'eseguibile è linkato alla libreria di runtime di debug, che è scritta in maniera da far emergere eventuali errori logici del programma (quindi è probabile che la tua assertion failed sia dovuta ad un errore logico che viene nascosto dalla libreria di runtime di release, più performante ma meno sicura).
Nella modalità release invece l'eseguibile di solito ha attive diverse ottimizzazioni, che impediscono al debugger di avere una corrispondenza precisa linea di assembler=>sorgente C++, ma che rendono l'esecuzione del programma più rapida oppure l'eseguibile più piccolo.