不!!!:-) 在尝试使用之前释放(src)是不行的!(在 *dest == src 的情况下,代码的第 2 行,即 free(*dest) 本质上与 free(src) 相同,然后您使用 src,从那时起它不指向正确分配的内存堵塞。)
尝试使用释放的内存会导致未定义的行为。当某些事情未定义时,任何事情都会发生!也许 free 已经将 src 中的第一个字节更改为 0(在这种情况下 strlen(src) == 0)或者 memcpy 检测到源内存没有正确分配或者可能发生了其他事情。不值得追究为什么会出现这种行为的问题。如果您更改构建设置(调试/优化等)或在不同的系统上构建您的程序(实际上是库,而不是您使用的编译器在这里有所不同),您可能会得到不同的结果。
无论如何,当 *dest == src 时,你不需要 free、strlen、malloc 和复制任何东西;你可以回来。
void str_cpy(char **des,char* src){
if(*des==src) return;
...
}
通常,使用您的函数的人会期望您不要对第二个参数 src 做任何有趣的事情,例如更改其内容或释放其内存。我还将参数类型更改为 const char * src。虽然这不会阻止您释放 src 内存块,但它会使函数的预期用途更加清晰。
实际上,函数签名还有另一个更大的问题。*dest 可能指向之前在堆中分配的内存(唯一可以使用 free(*dest) 的情况,当然假设 *dest != src)或之前分配的堆栈内存(在这种情况下 free(*dest) ) 不行),但也有可能它指向静态分配的内存(字符串文字)或不指向分配的内存周期。
标准库函数通过不使用此类签名(即使用 char ** 类型的参数)来避免这个问题。
与您正在做的最相关的功能的签名是:
char * strcpy(char *restrict s1, const char *restrict s2);
char * strncpy(char *restrict s1, const char *restrict s2, size_t n);
char * strdup(const char *s1);
更多信息请访问: http: //www.manpagez.com/man/3/strncpy/和http://www.manpagez.com/man/3/strncpy/
这些函数都不必担心内存分配的位置。这三个都要求它们的参数是有效的指针(指向静态或动态分配的(堆/堆栈)内存。我怀疑 strdup 实际上最适合您正在做的事情(您似乎想为重复的字符串分配新内存) . strcpy 和 strncpy 不分配新内存。(有关详细信息,请参阅上面的文档链接。)
你看到那里的模式了吗?strdup 返回一个指向新分配内存的指针(与 malloc 完全一样),并且 strcpy 和 strcpy 采用 char * 参数并且不分配内存。这些函数都不必处理您的函数所存在的问题,即确定(在 C 中不可能) *dest 指向的内存类型。Kernighan 和 Ritchie 选择这样做是有原因的 :-)
您可以提供明确说明 *dest 必须指向堆中先前分配的内存块或等于 NULL 的文档。然而,优秀的库设计者不会这样做,因为它将责任转嫁给用户(因为用户会犯错误)。
依赖文档(即让库设计者将责任传递给其用户)是一条危险的道路。最好完全避免这个问题。好的 C 代码从函数签名开始 :-)
最后一点:您在代码中使用了 strlen() 两次。出于性能原因,最好只使用一次并将其返回值存储在局部变量中,然后在当前调用 strlen() 的地方使用该变量。