如何避免 strcpy_s 缓冲区太小

Posted

技术标签:

【中文标题】如何避免 strcpy_s 缓冲区太小【英文标题】:How to avoid strcpy_s buffer too small 【发布时间】:2014-10-10 21:53:20 【问题描述】:

我需要将std::string data 复制到一个字符数组中。我的字符串的长度是可变的,但我的 char 数组的长度是固定的。

const int SIZE = 5;

char name[SIZE];
std::string data = "1234567890";

strcpy_s(name, 5, data.c_str()); //causes a buffer is too small assertion
strcpy_s(name, 11, data.c_str());//copies fine (length of data plus null)
strcpy_s(name, sizeof(data), data.c_str()); // copies fine

如何每次只安全地复制数组的长度?没有得到断言,也没有导致缓冲区溢出。

我应该每次都这样吗?

std::string toCopy = data.substr(0,SIZE-1);
strcpy_s(name, toCopy.c_str());

【问题讨论】:

如果这是C++11,你可以只使用字符串的缓冲区。 是的,它的 C++ll。你能举个例子说明你的意思吗?? 如果你的意思是“mstrcpy_s(name, data.c_str());”这给了我想要避免的断言错误。 只需执行s2 = s1;(或需要的子字符串),而不是使用 C 字符串。当您需要字符指针时,使用&s2[0] 表示可修改的指针,直到最后一个空终止符之前,或使用c_str() 表示不可修改的指针。 【参考方案1】:

将strncpy_s 与_TRUNCATE 一起使用

例如:

strncpy_s(name, data.c_str(), _TRUNCATE);

将尽可能多地复制以填充 name 缓冲区,同时仍将空终止考虑在内(与传统的 strncpy 不同)。

【讨论】:

【参考方案2】:

以下内容返回 ERANGE 结果,因为您必须为终止 NULL 字符留出空间。变量“数据”包含 10 个元素。当 strcpy_s 达到约束 '5' 时,它无法找到终止 NULL 并返回 ERANGE。

strcpy_s(name, 5, data.c_str());

Microsoft Documentation

strcpy_s函数复制strSource地址中的内容, 包括终止空字符,到的位置 由 strDestination 指定。目标字符串必须很大 足以容纳源字符串及其终止空字符。 如果源和目标未定义 strcpy_s 的行为 字符串重叠。

替代方法

  string data = "0123456789";
  int SIZE = 5;
  char name[SIZE];

  size_t length = data.copy( name, 0, 5 );
  buffer[ length ] = '\0';

【讨论】:

谢谢,这对我有用。我有足够的空间存放字符串,但没有复制nullchar。真的很奇怪的行为,而且绝对是一个奇怪的错误信息。

以上是关于如何避免 strcpy_s 缓冲区太小的主要内容,如果未能解决你的问题,请参考以下文章

调试断言失败(缓冲区太小)构造函数初始化

oracle expdp导出报错“字符串缓冲区太小”

执行动态SQL报“字符串缓冲区太小”错误,请问各位高手怎么解决啊

strncpy_s - 缓冲区太小断言

Oracle 数据访问 ORA-06512: 字符串缓冲区太小

Linux字符设备——如果读取缓冲区太小怎么办?