我正在学习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因为我想尝试这个新功能并知道它是如何工作的。
答案 0 :(得分:2)
您需要再使用一个字符来终止字符('\0'
),因此您需要将strlen("Hello!\n")
替换为strlen("Hello!\n") + 1
。您可以将此长度存储在某个变量中,而不是再次调用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;
答案 1 :(得分:2)
我接受了我的评论,我更仔细地阅读了the documentation。您的代码传递了无效参数,并且正在调用无效参数处理程序。也许这就是发生的事情。即:
p=(char *)malloc(sizeof(char)*strlen("Hello!\n"));
此行为7个字符分配空间,这是字符串的长度,但没有足够的空间用于空终结符。 (这通常是一个错误)
strncpy_s
的文档说:这些函数尝试将strSource的前D个字符复制到strDest,其中D是count的较小者和strSource的长度。 如果这些D字符符合在strDest(其大小以numberOfElements给出)并仍为空终结符留出空间,则会复制这些字符并附加终止空值; 否则,strDest [0]设置为空字符,并调用无效参数处理程序,如参数验证中所述。
您是否可能看到“无效参数处理程序”?
答案 2 :(得分:2)
'安全性增强'字符串函数主要用于在遇到问题时崩溃。
来自Microsoft's docs on strncpy_s()
:
这些函数尝试将strSource的前D个字符复制到 strDest,其中D是计数中的较小者和strSource的长度。 如果这些D字符符合strDest(其大小为 numberOfElements)并且仍为空终止符留出空间 复制这些字符并附加终止空值; 否则,strDest [0]设置为空字符和无效字符 调用参数处理程序,如参数验证中所述。
上段有例外。如果count是_TRUNCATE, 然后尽可能多地复制适合strDest的strSource 仍然留下了终止null的空间,它始终是附加的。
description of the Paramter Validation是:
找到无效参数时的C运行时的行为是 调用当前分配的无效参数处理程序。默认 无效参数调用Watson崩溃报告,这会导致 应用程序崩溃并询问用户是否要加载崩溃 转储到Microsoft进行分析。在调试模式下,参数无效 也会导致断言失败。
使用此功能可以更改此行为 _set_invalid_parameter_handler将无效参数处理程序设置为您自己的函数。 ...
您的示例程序提供的缓冲区太小了char
(空终结符没有空间)。
因此,除非您明确更改strxxxx_s
函数遇到错误时应执行的操作,否则您的程序将因设计而崩溃。这个想法是崩溃比可能打开安全漏洞的bug更好。
答案 3 :(得分:1)
strlen(s)
只会告诉你没有NULL终结符的字符串的长度。要分配复制字符串的空间,通常使用strlen(s)+1
为NULL终止符添加空间。
答案 4 :(得分:1)
您需要分配strlen(“Hello!\ n”)+ 1(对于null终止符)。而sizeof(char)完全没有意义,因为sizeof(char)在所有平台上都保证为1。
答案 5 :(得分:0)
如果您使用的是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
如果您需要字符串中的字符*,则可以使用p.c_str()