1

我知道当您使用 strcpy_s 时,您应该提供目标字符串的大小作为第二个参数。但如果目标字符串是 char* ,那么我不确定我做对了。我举了三个例子:

char* dest = new char;

// Example 1
CString strTemp = "Bob";
strcpy_s(dest, strTemp.GetLength() + 1, strTemp);   

// Example 2
strcpy_s(dest, strlen("Jose")+1, "Jose");

// Example 3 
char* c = new char;
c = "Richard";
strcpy_s(dest, strlen(c) + 1,c);        

这一切都正确吗?

4

4 回答 4

3

在所有三个示例中,您都在传递字符串的大小。您应该传递目标缓冲区的大小,以便strcpy_s验证不会出现缓冲区溢出。

传递源字符串的大小会破坏该检查。strcpy_s已经知道源字符串的大小;它可以尽strlen(src)你所能。它不能做的是自动检测目标缓冲区的大小。它需要被告知它的大小。

const int SIZE = 2048; // an arbitrary large number
char* dest = new char[SIZE];

std::errno_t result = strcpy_s(dest, SIZE, src);   

if (result != 0) {
    // error
}

您的所有示例都应该类似于上面的内容:

  • dest指向的不是单个字符,而是一大堆字符。
  • 第二个参数是目标缓冲区的大小。
  • 确保检查返回码是否有错误。

注意:尽量避免在 C++ 中使用 C 字符串。使用起来要好得多std::string。它会为你处理所有这些混乱。您不必处理内存分配或担心缓冲区溢出。

于 2020-01-10T01:16:24.400 回答
1

请注意,您应该为目的地分配正确的大小,因此替换

char* dest = new char;分配一个字符

char* dest = new char[strlen(strTemp)+1];.

请注意,这cString不是一种类型,因此用 or 替换 CString strTemp = "Bob";char* strTemp = "Bob";最后const char* strTemp = "Bob";一个等同于auto strTemp = "Bob";)。

注意c style strings 不是objects所以strTemp.GetLength()是无效的。将其替换为并包含包含该功能strlen(strTemp)的标题。<cstring>strlen()

最后,您的代码应如下所示

#include<iostream>
#include<cstring>
using namespace std;
int main(){

    auto strTemp = "Bob";
    char* dest = new char[strlen(strTemp)+1];
    strcpy_s(dest, strlen(strTemp) + 1, strTemp);   
    cout<<dest;
}
于 2020-01-10T01:28:08.053 回答
1

这一切都正确吗?

没有一个例子是正确的。

char* dest = new char;

你已经分配了一个char. 它可以表示的唯一字符串是空字符串。

char* c = new char;
c = "Richard";

通过分配c指向其他地方,您丢失了由new. 因此,您不能再将该值传递给delete. 这称为内存泄漏。

此外,由于 C++11,这是格式错误的,因为字符串文字不再可转换为指向非 const char 的指针。格式错误意味着编译器不需要编译您的程序,而是需要向您发出诊断消息,通知您格式错误。

strcpy_s(dest, strlen(c) + 1,c);

您应该传递目标缓冲区的大小;不是源数据的大小。在这种情况下,目标缓冲区太小,但是因为您传递了错误的值,所以错误没有被捕获并且行为未定义。

正如我提到的,传递目标缓冲区的大小:

auto error = strcpy_s(dest, 1, "Richard");

这会安全地导致错误而不是未定义的行为 - 或者它可能会安全地中止程序或根据实现执行其他操作。您可以控制约束处理程序以获得所需的行为。

当然,您可能希望分配足够的内存以便复制工作:

std::size_t destsz = 1024;
char* dest = new char[destsz];

你知道你分配的大小。只需将其传递给strcpy_s

auto error = strcpy_s(dest, destsz, "Richard");

不要忘记清理:

delete[] dest;

PS C++ 标准库不提供strcpy_s. 这是一个非标准功能。它仅在 C 语言中是标准的(但提供它的实现是可选的)。

PSS 不要new用于分配字符串。std::string在 C++ 中使用。你std::string可以像这样复制:

std::string c = "Richard";
std::string dest = c;

使用这种方法更难泄漏内存或产生更严重的错误。

于 2020-01-10T01:23:25.277 回答
0

如果在将字符串复制到其中之前分配内存,则使用字符串复制函数会显示思维混乱导致公然浪费:只需使用memcpy()(或std:copy_n())。

strcpy_s()需要指向目标的指针、目标缓冲区大小和指向源的指针。
如果您猜测缓冲区大小是从源中派生的所需的大小,而不是知道它,使用strcpy()而不是那种复杂的方式来(希望)以较低的效率编写相同的内容。

总之,您的所有用途都是错误的。

顺便说一句:
new char分配一个 solitary char,而不是适当大小的数组。改为使用new char [n]
你真的需要复制字符串,或者你真的可以只传递一个指针吗?
流程范围的约束处理程序不需要做你想做的事。或者实际上任何有用的东西。

于 2020-01-10T01:28:51.997 回答