This is an example of how pointers and arrays are not equivalent in C. In particular: the rule that arrays decay to pointers is not applied recursively
This means that an array can be used as a pointer, but a pointer-to-array cannot be used as a pointer-to-pointer. This is what you are experiencing here. This is why the compiler complains about mismatched types when you don't cast &str explicitly to char**. That should be your first clue that something is wrong.
The reason that this causes a segfault is this: The way that an array automatically decays to a pointer is by turning into the address of its first element. A pointer to an array is likewise a pointer to the address of the array's first element. So a pointer-to-array and array-as-pointer are the same thing. In other words str, when passed as a pointer, has a value identical to &str. So if you try to make &str into a pointer-to-pointer, it doesn't work, since is just a (single-level) pointer.
For example,
void f(char** pp);
void g(char* p);
char[] str = "abcd"; // Lets say this is allocated at address 0x1234
g(str); // Value of p in g is 0x1234 (by automatic conversion of char[4] to char*)
char* p_str = &str; // Value of p_str is 0x1234
g(p_str); // Value of p in g is again 0x1234
f(str); // Illegal, no conversion of char[] to char** (obvious)
f(p_str); // Illegal, no conversion of char* to char** (obvious)
f(&str); // Illegal, no conversion of char*[4] to char** (less obvious)
f((char**)p_str); // Ok, now you're overriding the typecheck
But after that last call to f((char**)p_str)
, the value of pp in f is still going to be 0x1234 because you haven't modified the value of p_str, you've only suppressed the type-checker's complaint. This means that *pp is going to be 'a', not a pointer to the address that contains 'a'. And that's why you get a segfault when f tries to execute **pp.