Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/145.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
c++;:新的动态分配操作员是否检查内存安全? 我的问题来自于我的C++练习(C++中的编程抽象,2012版本,练习12.2)。这是:_C++_Dynamic_Heap_Allocation - Fatal编程技术网

c++;:新的动态分配操作员是否检查内存安全? 我的问题来自于我的C++练习(C++中的编程抽象,2012版本,练习12.2)。这是:

c++;:新的动态分配操作员是否检查内存安全? 我的问题来自于我的C++练习(C++中的编程抽象,2012版本,练习12.2)。这是:,c++,dynamic,heap,allocation,C++,Dynamic,Heap,Allocation,strcpy的定义是危险的。危险源于事实 strcpy无法检查内存中是否有足够的空间 接收副本的字符数组,从而增加机会 缓冲区溢出错误的原因。然而,有可能消除很多 通过使用动态分配为用户创建内存空间来消除危险 复制的字符串。写一个函数 char *copyCString(char *str); 为C样式字符串str分配足够的内存,然后 将字符与终止的空字符一起复制到 新分配的内存 我的问题是: 这种新方法真的安全吗?为什么安全? 我的意思是,有点激进,如果堆中没有足够的空间怎么办? 新的操作员

strcpy的定义是危险的。危险源于事实 strcpy无法检查内存中是否有足够的空间 接收副本的字符数组,从而增加机会 缓冲区溢出错误的原因。然而,有可能消除很多 通过使用动态分配为用户创建内存空间来消除危险 复制的字符串。写一个函数

char *copyCString(char *str);
为C样式字符串str分配足够的内存,然后 将字符与终止的空字符一起复制到 新分配的内存

我的问题是: 这种新方法真的安全吗?为什么安全? 我的意思是,有点激进,如果堆中没有足够的空间怎么办?
新的
操作员是否能够检查空间可用性,并在空间不足时优雅地降落?
这会导致其他类型的“溢出”吗?

如果
new
无法分配请求的内存,它应该抛出
std::bad_alloc
异常(但更多信息请参见下文)。之后,堆栈将被解缠到匹配的异常处理程序,然后由您的代码决定从那里执行什么操作

如果您确实想/需要确保不会抛出异常,那么可以使用
nothrow
版本的
new
返回一个指向信号失败的空指针——但这几乎完全是为了与C兼容而包括的,并且不经常使用(或有用)

对于问题中提到的情况类型,您通常希望使用
std::string
,而不是自己分配空间

还要注意的是,在许多现代系统中,
new
的概念在出现故障时抛出或返回空指针,这一概念实际上是相当陌生的。实际上,Windows通常会尝试扩展分页文件以满足您的请求。Linux有一个“OOMKiller”进程,它将尝试查找“坏”进程,并在内存耗尽时杀死它们以释放内存


这样,即使C++标准(和C标准)规定了如果分配失败,应该发生什么,那在实际生活中很少发生。

< P>新操作符如果不能定位内存,则抛出Bad OLL异常,除非指定了NoLoad。如果指定常量nothrow,如果无法分配内存,将返回NULL指针。

strcpy的代码不安全,因为它将尝试在分配给dst指针的内存之外进行复制。例如:

int main()
{
    const char* s1 = "hello"; // allocated space for 6 characters
    char* s2 = new char[ 2 ]; // allocated space for 2 characters.
    strcpy( s2, s1 );
    cout << s2 << endl;

    char c; cin >> c;
    return 0;
}
intmain()
{
const char*s1=“hello”//为6个字符分配了空间
char*s2=新字符[2];//为2个字符分配了空间。
strcpy(s2,s1);
coutc;
返回0;
}
这将打印正确的值“hello”,但请记住,指针s2仅分配了2个字符的空间。因此,我们可以假设其他字符被写入后续的内存插槽,这是不安全的,因为我们可能会覆盖数据或访问无效内存

考虑这个解决方案:

char* e4_strdup( const char*& c )
{
    // holds the number of space required for the c-string
    unsigned int sz{ 0 };

    // since c-style strings are terminated by the '\0' character,
    // increase the required space until we've found a '\0' character.
    for ( const char* p_to_c = c; *p_to_c != '\0'; ++p_to_c )
        ++sz;

    // allocate correct amount of space for copy.
    // we do ++sz during allocation because we must provide enough space for the '\0' character.
    char* c_copy{ new char[ ++sz ] }; // extra space for '\0' character.
    for ( unsigned int i{ 0 }; i < sz; ++i )
        c_copy[ i ] = c[ i ]; // copy every character onto allocated memory

    return c_copy;
}
char*e4\u strdup(const char*&c)
{
//保存c字符串所需的空间数
无符号整数sz{0};
//由于c样式字符串以“\0”字符结尾,
//增加所需的空间,直到找到“\0”字符。
for(const char*p_to_c=c;*p_to_c!='\0';++p_to_c)
++深圳;
//为复制分配正确的空间量。
//我们在分配期间执行++sz,因为我们必须为“\0”字符提供足够的空间。
char*c_copy{new char[++sz]};//为'\0'字符留出额外空间。
for(无符号整数i{0};i

如果内存不足,新的操作符仍将返回std::bad_alloc异常。

谢谢您的回答!我想我明白了。但这个问题是故意设计的,目的是让读者在分配空间时无所事事。因此,他们可以获得一种动态分配的感觉。它在“动态内存管理”一章中。@ZongyaoJin:是的,这很好,而且是一个非常合理的学习方法。然而,不幸的是,大多数书似乎都没有足够详细地教授动态内存管理,因此没有真正发挥作用。再次感谢您的补充!我懂了。我知道这几乎永远不会发生,特别是对于像我这样的新程序员来说。这只是提到的关于安全的问题,没有提到为什么新的
是一个更好的策略。所以,我对此很好奇。无论如何,非常感谢你!一个恼人的怪癖是,可能会重载全局
操作符new()
,以返回空指针,而不是引发异常;因此,依赖于
new
中的值而从不为空的代码可能会被另一个翻译单元中的某个操作破坏。@MattMcNabb:肯定有人可以这样做——如果分配函数有一个非抛出异常规范,那么它是必需的。否则,它(显然)是未定义的行为:“任何未能分配存储的其他分配函数都只能通过抛出一个与std::bad_alloc(18.6.2.1)类型的处理程序(15.3)匹配的异常(15.1)来表示失败。”(§[basic.stc.dynamic.allocation]/3)(从措辞上看,这确实应该是一个可诊断的错误,但我怀疑大多数编译器是否能够诊断)。在您的第一个示例中,大小分别为
6
2
。您是正确的,我忽略了“\0”字符,另一个是我在编辑文章时犯的错误。谢谢。修复了。
char* e4_strdup( const char*& c )
{
    // holds the number of space required for the c-string
    unsigned int sz{ 0 };

    // since c-style strings are terminated by the '\0' character,
    // increase the required space until we've found a '\0' character.
    for ( const char* p_to_c = c; *p_to_c != '\0'; ++p_to_c )
        ++sz;

    // allocate correct amount of space for copy.
    // we do ++sz during allocation because we must provide enough space for the '\0' character.
    char* c_copy{ new char[ ++sz ] }; // extra space for '\0' character.
    for ( unsigned int i{ 0 }; i < sz; ++i )
        c_copy[ i ] = c[ i ]; // copy every character onto allocated memory

    return c_copy;
}