And one more thing:
You define the return value as char*, then you proceed to return "copy" with malloc, but if it fails, you return a const char*, which might be free'd. You should malloc this string.
char *_string_duplicate(const char *string)
{
char *copy = (char*) malloc(sizeof(*copy) * (strlen(string) + 1));
if (copy == NULL)
{
// return "Not enough memory for error message";
const char* error_message = "Not enough memory for error message";
size_t len = strlen(error_message);
char* error = (char*) malloc(len*sizeof(char) + 1);
strcpy(error, error_message);
return error;
}
strcpy(copy, string);
return copy;
}