Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/64.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++;有内存问题吗?_C++_C_Memory Management_Memo - Fatal编程技术网

C++ 为什么是C/C++;有内存问题吗?

C++ 为什么是C/C++;有内存问题吗?,c++,c,memory-management,memo,C++,C,Memory Management,Memo,我读过很多程序员在用C/C++编程时说的话和写的话,其中有很多与内存有关的问题。我计划学习用C/C++编程。我有C/C++的初学者知识,我想看看为什么C/C++在内存管理方面会有问题。请提供一些示例。这在C/C++中通常被称为不同的原因是许多现代语言执行内存管理和垃圾收集。在C/C++中,情况并非如此(无论好坏)。您需要手动分配和释放内存,并且未能正确地执行内存泄漏,这在执行内存管理的语言中是不可能的。 < P> C和C++中的一个常见内存管理问题与数组的边界检查缺乏相关。与java(例如)不同

我读过很多程序员在用C/C++编程时说的话和写的话,其中有很多与内存有关的问题。我计划学习用C/C++编程。我有C/C++的初学者知识,我想看看为什么C/C++在内存管理方面会有问题。请提供一些示例。

这在C/C++中通常被称为不同的原因是许多现代语言执行内存管理和垃圾收集。在C/C++中,情况并非如此(无论好坏)。您需要手动分配和释放内存,并且未能正确地执行内存泄漏,这在执行内存管理的语言中是不可能的。

< P> C和C++中的一个常见内存管理问题与数组的边界检查缺乏相关。与java(例如)不同,C和C++不检查以确保数组索引位于实际数组边界内。因此,很容易意外地覆盖内存。例如(C++):


除了您的代码将覆盖不应该存在的内存外,不会出现与上述代码相关的编译或运行时错误。

基本上,在这些语言中,您必须手动请求在编译时不是已知局部变量的每一位内存,并且在不再需要时必须手动释放它。这些库(所谓的智能指针)可以在某种程度上自动化这个过程,但它们并不适用于任何地方。此外,通过指针算法访问内存的方式绝对没有限制

手动内存管理可能会导致许多错误:

  • 如果您忘记释放一些内存,则内存泄漏
  • 如果使用的内存超过了给定指针的请求,则会出现缓冲区溢出
  • 如果您释放内存并继续使用“悬空指针”指向它,则您有未定义的行为(通常程序崩溃)
  • 如果您错误计算了指针算术,则表明您发生了崩溃或数据损坏

这些问题很难诊断和调试。

< P>有很多方法可以破坏或泄漏C或C++中的内存。这些错误是最难诊断的错误之一,因为它们通常不容易再现

例如,很容易无法释放已分配的内存。例如,这将执行“双重释放”,尝试释放
a
两次,但未能释放
b

char *a = malloc(128*sizeof(char));
char *b = malloc(128*sizeof(char));
b = a;
free(a);
free(b); // will not free the pointer to the original allocated memory.
下面是一个破坏任意内存的缓冲区溢出示例。这是缓冲区溢出,因为您不知道
str
的长度。如果长度超过256字节,那么它会将这些字节写入内存中的某个位置,可能会覆盖您的代码,可能不会

void somefunc(char *str) {
    char buff[256];
    strcpy(buff, str);
}
我计划学习C/C语言编程++

你这到底是什么意思?你想学习C语言编程,还是想学习C++编程?我不建议同时学习两种语言


从用户的角度来看,C++中的内存管理比C语言要简单很多,因为大部分都是用类封装的,例如:代码> STD::vector < /代码>。从概念的角度来看,C的内存管理要简单得多。基本上,只有
malloc
free
:)

当使用new获取内存块时,操作系统保留的大小可能大于您的请求,但决不能小于。由于这一点以及delete不会立即将内存返回操作系统的事实,当您检查程序正在使用的整个内存时,您可能会认为您的应用程序存在严重的内存泄漏。因此,检查整个程序使用的字节数不应被用作检测内存错误的方法。只有当内存管理器指示使用的内存大量持续增长时,才应怀疑内存泄漏

>我可以诚实地说,在C++编程中,我没有内存分配的“问题”。我上一次内存泄漏是在10年前,是因为我盲目的愚蠢。如果您使用RAII、标准库容器和少量常识编写代码,那么问题实际上并不存在。

到目前为止没有提到的一件事是性能以及为什么要手动管理内存。 即使使用valgrind等强大的现代编程工具,也很难准确地管理内存,特别是当程序变得更加复杂时(尤其是当您使用线程时,以及当内存片段的生命周期变得复杂时(即当很难准确地判断您何时不需要一段信息时))

那么,您为什么要手动管理内存,原因如下: --了解它是如何工作的 --要实现垃圾收集/自动内存管理,您需要手动 --对于一些较低级别的东西,例如内核,您需要手动控制内存所能提供的灵活性。 --最重要的是,如果您正确地进行手动内存管理,您可以获得较大的加速/较低的内存开销(更好的性能),这是垃圾收集的一个相关问题(尽管随着编写更好的垃圾收集器(如hotspot jvm)而变得更好)你无法控制内存管理,所以很难使用实时功能(保证某些目标(如汽车制动器和起搏器)的截止日期,尝试特殊的实时gc)和与用户交互的程序可能会冻结一点或延迟(这对游戏来说很糟糕)

<> P>很多“现代C++”(已经说过C++可以被视为多语言,取决于你如何使用它),而不是C类(或X和Y C++特性)经常使用简单的可选GC /自动内存管理来使用折衷(注意可选GC在内存管理方面可能更差,然后是强制性的)
void somefunc(char *str) {
    char buff[256];
    strcpy(buff, str);
}
struct student
{
 char name[20];
 int roll;
 float marks;
}s[100];
struct student *s;

s=(struct student *)malloc(sizeof(struct student));

scanf("%s %d %f",s->name,s->roll,s->marks);
free(s);