char* copyStr(const char* someStr)
char* copyStr(const char* someStr)
以下 C 代码有什么问题?
char* copyStr(const char* someStr)
{
char buf[100];
sprintf(buf, “%s”, someStr);
return buf;
}
您的代码中存在 2 个主要问题:
如果 sprintf(buf, “%s”, someStr);
将尝试将超过 100 个字节存储到 buf
,如果 somStr
指向的字符串超过 99 个字节加上空终止符,导致未定义的行为。此调用等同于具有相同问题的 strcpy
。您应该始终使用 snprintf
而不是 sprintf
,传递目标数组的长度,从而防止缓冲区溢出。
return指向本地数组的指针是不正确的,因为对象将在退出函数后立即超出范围:调用者将调用取消引用该指针的未定义行为。
为了您的目的,您应该分配一块内存,将字符串复制到其中,并 return 指向它的指针:
#include <stdlib.h>
#include <string.h>
char *copyStr(const char *someStr) {
size_t len = strlen(someStr);
char *p = malloc(len + 1);
if (p != NULL) {
memcpy(p, someStr, len + 1);
}
return p;
}
这正是 POSIX 中定义的函数 strdup
的语义,并标准化了即将发布的 C23 标准:
char *strdup(const char *s);
以下 C 代码有什么问题?
char* copyStr(const char* someStr)
{
char buf[100];
sprintf(buf, “%s”, someStr);
return buf;
}
您的代码中存在 2 个主要问题:
-
如果
sprintf(buf, “%s”, someStr);
将尝试将超过 100 个字节存储到buf
,如果somStr
指向的字符串超过 99 个字节加上空终止符,导致未定义的行为。此调用等同于具有相同问题的strcpy
。您应该始终使用snprintf
而不是sprintf
,传递目标数组的长度,从而防止缓冲区溢出。return指向本地数组的指针是不正确的,因为对象将在退出函数后立即超出范围:调用者将调用取消引用该指针的未定义行为。
为了您的目的,您应该分配一块内存,将字符串复制到其中,并 return 指向它的指针:
#include <stdlib.h>
#include <string.h>
char *copyStr(const char *someStr) {
size_t len = strlen(someStr);
char *p = malloc(len + 1);
if (p != NULL) {
memcpy(p, someStr, len + 1);
}
return p;
}
这正是 POSIX 中定义的函数 strdup
的语义,并标准化了即将发布的 C23 标准:
char *strdup(const char *s);