Mogę się mylić, więc liczę, że ktoś mnie ewentualnie poprawi lub potwierdzi, co tu napisałem:
Inicjalizując str2 przypisujesz do tego wskaźnika adres literału, który znajduje się w sekcji programu, gdzie zapisane są stałe. Wczytując ze strumienia dane, wskaźnik str2 jest traktowany jak adres bufora i następuje próba zapisu do tego bufora - próbujesz zmienić wartość danej w sekcji read-only, czego nie omieszka wytknąć Ci system operacyjny, kończąc działanie Twojego programu. Dodaj consta przed str2, żeby dowiedzieć się o próbie zapisu już na etapie kompilacji.
Z kolei opcja z tablicą działa, ponieważ tablica arr jest umiejscowiona na stosie, a nie w sekcji stałych. Więc dopóki tablica arr jest zdatna do użytku (czyli gdy znajdujemy się w zakresie ważności tej zmiennej tablicowej), to możemy bezkarnie zapisać do bufora pod adresem arr 30 bajtów.