In your example you made many, many mistakes.
First of all look at documentation about which function is safe to call from
signal handlers:
https://www.securecoding.cert.org/confluence/display/seccode/SIG30-C.+Call+only+asynchronous-safe+functions+within+signal+handlers
Of course functions that can allocate memory is not safe to call, because of it is not safe to call malloc.
Because of it is not right to call printf or std::ostream::opeartor<< (std::cout <<) in signal handler.
Second, in documentation (type man 3 sleep) clearly written it is not safe mix sleep and alarm,
Third you not wait enough in main function, so it can exit before the second alarm handler run.
Here is how it can be done:
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
volatile sig_atomic_t done = 0;
void alarm2(int signo)
{
write(STDOUT_FILENO, "alarm2\n", sizeof("alarm2\n") - 1);
done = 1;
}
void alarm1(int signo)
{
signal(SIGALRM, alarm2);
write(STDOUT_FILENO, "ctrl+C\n", sizeof("ctrl+C\n") - 1);
alarm(10);
}
int main()
{
signal(SIGALRM, alarm1);
alarm(3);
while (done == 0)
sleep(1); //sleep can be wake up by alarm signal, so check flag
}