如何使用visual c++中的strncpy_s函数
How to use the strncpy_s function from visual c++?
我正在C++中学习一些新东西,我试图从Visual C++中测试这个strncpy_s函数。然而,当程序崩溃时,我遇到了一些问题,我不知道发生了什么,但我确信这是一个非常愚蠢的问题。源代码是这样的:
#include "stdafx.h"
#include <iostream>
#include <cstdio>
#include <cstring>
int main()
{
char *p;
p=(char *)malloc(sizeof(char)*strlen("Hello!n"));
strncpy_s(p,strlen("Hello!n"),"Hello!n",strlen("Hello!n"));
std::cout << p;
std::cout << strlen("Hello!n") << std::endl;
return 0;
}
正如我所说,我不使用std::string,因为我想尝试这个新函数并了解它是如何工作的。
我收回了我的评论,我更仔细地阅读了文档。您的代码正在传递无效的参数,并且正在调用无效的参数处理程序。也许这就是正在发生的事情。即:
p=(char *)malloc(sizeof(char)*strlen("Hello!n"));
这一行为7个字符分配了空间,这是字符串的长度,但没有足够的空间容纳null终止符。(这通常是一个错误)
strncpy_s
的文档中写道:这些函数试图将strSource的前D个字符复制到strDest,其中D是strSource的计数和长度中的较小值如果这些D字符适合strDest(其大小为numberOfElements)中的,并且仍为null终止符留有空间则复制这些字符并附加一个终止null否则,strDest[0]设置为null字符,并调用无效参数处理程序,如参数验证中所述。
您是否可能看到"无效参数处理程序"?
终止字符(' '
)还需要1个字符,因此需要用strlen("Hello!n") + 1
替换strlen("Hello!n")
。您可以将此长度存储在某个变量中,而不是再次调用strlen
。此外,由于您使用C++,您可以使用new / delete
而不是malloc / free
:
int len = strlen("Hello!n") + 1;
char *p;
p = new char[len];
strncpy_s(p, len, "Hello!n", len);
std::cout << p << len << std::endl;
delete[] p;
"安全增强"字符串函数本质上是为在遇到问题时崩溃而设计的。
来自微软关于strncpy_s()
:的文档
这些函数试图将strSource的前D个字符复制到strDest,其中D是计数和strSource长度中的较小值。如果这些D字符适合strDest(其大小给定为numberOfElements),并且仍然为null终止符留出空间,然后复制这些字符,并附加终止null;否则,strDest[0]被设置为null字符和无效字符参数处理程序被调用,如参数验证中所述。
上述段落有一个例外。如果计数是_TRUNCATE,则在仍然为总是附加的终止null留有空间。
参数验证的描述是:
当发现无效参数时,C运行时的行为是调用当前分配的无效参数处理程序。默认值无效参数调用Watson崩溃报告,导致应用程序崩溃,并询问用户是否要加载崩溃转储到Microsoft进行分析。在调试模式下,一个无效参数也会导致断言失败。
此行为可以通过使用函数来更改_set_invalid_parameter_handler将无效参数处理程序设置为您自己的函数。。。
您的示例程序提供的缓冲区太小了一个char
(没有空终止符的空间)。
因此,除非您特别更改strxxxx_s
函数在遇到错误时应该执行的操作,否则您的程序将在设计时崩溃。这个想法是,崩溃比可能打开安全漏洞的漏洞要好。
strlen(s)
只会告诉您不带NUL终止符的字符串的长度。要分配用于复制字符串的空间,通常使用strlen(s)+1
为NUL终止符添加空间。
您需要分配strlen("Hello!\n")+1(用于null终止符)。sizeof(char)是完全没有意义的,因为在所有平台上sizeof(char)都保证为1。
如果使用C++,为什么要使用malloc或char*?
std::string p = "Hello!n";
std::cout << p;
std::cout << p.length();
或
std::string* p = new std::string("Hello!n");
std::cout << p;
std::cout << p->length();
但要回答您最初的问题,您可能需要使用strlen(p) + 1
如果您需要字符串中的char*,则可以使用p.c_str()
- "error: no matching function for call to"构造函数错误
- 什么时候调用组成单元对象的析构函数
- 继承函数的重载解析
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- C++模板来检查友元函数的存在
- 递归函数计算序列中的平方和(并输出过程)
- 对RValue对象调用的LValue ref限定成员函数
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 为什么使用 "this" 指针调用派生成员函数?
- 将对象数组的引用传递给函数
- 函数调用中参数的顺序重要吗
- 函数向量_指针有不同的原型,我可以构建一个吗
- 使用不带参数的函数访问结构元素
- 代码在main()中运行,但在函数中出现错误
- 内置函数可查看CPP中的成员变量
- 如何获取std::result_of函数的返回类型
- 如何在c++中为模板函数实例创建快捷方式
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗