The problem is that you do not do any "hard copy" of the memory cells anywhere, you just change pointers to point at different places. Strings are arrays and therefore have to be copied using the strcpy or memcpy functions.
char* str_2 = new char[7];
allocates dynamic memory. str_2 = "string";
lets the pointer str_2 point at a completely different memory cell, forgetting that it used to point at the allocated dynamic memory. Since there is no remaining reference to that memory, you know how a memory leak bug.
str_2
now points at a constant string literal "string" which resides in read-only memory.
str_2[2] = 'a';
attempts to modify that memory, which is undefined behavior and you get a crash.
To understand why the str_1 case works, it is important to grasp the programming concepts intialization and assignment. The case of 'str_1' works because you allocate 7 bytes and then initialize those bytes to contain "string". At variable initialization is the only place where =
will result in a hard copy from the read-only memory where the actual string literal "string" resides, to the stack in RAM where str_1 is allocated.