No wonder if you don't hold up its safety invariants, stated in the doc comments upfront:
/// # Safety
/// * `ptr` must be correctly aligned for its type and non-zero.
/// * `ptr` must be valid for reads of `elts` contiguous elements of type `T`.
/// HERE >>> * Those elements must not be used after calling this function unless `T: Copy`.
TL;DR: you have a double free. arr.as_ptr() doesn't give away ownership, so you now have two Vecs that try to drop the same elements.
Yeah, that's the exact same thing again. The safety invariant states that you can re-use the source buffer if T: Copy (which String isn't, but u32 is), because in that case, it can't have a destructor, so destroying the original vector only deallocates the buffer, it doesn't incorrectly try to free two sets of copies of the same elements.
When you use ptr::copy on a String, you end up with two copies of the string that both own the same string data. Then, once the second copy of the string goes out of scope, it tries to destroy the string data, but it has already been destroyed by the other copy. Hence the error.
I recommend adding a Copy bound to your function so that it can only be used with types that are valid to copy: