这个问题可能听起来相当简单,但这是我与另一位与我合作的开发人员的辩论.
我正在小心处理堆栈分配的东西,而不是堆分配它们.他正在跟我说话,看着我的肩膀并评论说这没有必要,因为他们的表现是明智的.
我一直认为堆栈的增长是恒定的时间,并且堆分配的性能取决于堆的当前复杂性(用于找到合适大小的孔)和解除分配(折叠孔以减少碎片,如如果我没有弄错的话,许多标准库实现在删除期间需要时间来完成此操作.
这让我觉得可能非常依赖于编译器.特别是对于这个项目,我使用Metrowerks编译器来实现PPC架构.对这种组合的洞察力将是最有帮助的,但总的来说,对于GCC和MSVC++,情况如何?堆分配不如堆栈分配高吗?没有区别吗?或者差异是如此微小,它变得毫无意义的微优化.
我已经搜索过了,但我对这三个概念并不是很了解.我何时必须使用动态分配(在堆中)以及它的真正优势是什么?静态和堆栈有什么问题?我可以编写整个应用程序而无需在堆中分配变量吗?
我听说其他语言包含了"垃圾收集器",所以你不必担心内存.垃圾收集器做什么?
您可以自己操作内存,而不能使用此垃圾收集器吗?
有人告诉我这个声明:
int * asafe=new int;
Run Code Online (Sandbox Code Playgroud)
我有一个"指针指针".这是什么意思?它不同于:
asafe=new int;
Run Code Online (Sandbox Code Playgroud)
?
我已经编程了一段时间,但它主要是Java和C#.我实际上从来没有必须自己管理内存.我最近开始用C++编程,我有点困惑的是什么时候我应该把东西存放在堆栈上以及何时将它们存储在堆上.
我的理解是,非常频繁访问的变量应该存储在堆栈中,对象,很少使用的变量和大型数据结构都应该存储在堆上.这是正确的还是我错了?
所以,我需要一些帮助.我正在用C++开发一个项目.但是,我想我已经设法破坏了我的堆.这是基于我std::string
向一个类添加了一个并从另一个类中赋值的事实std::string
:
std::string hello = "Hello, world.\n";
/* exampleString = "Hello, world.\n" would work fine. */
exampleString = hello;
Run Code Online (Sandbox Code Playgroud)
使用堆栈转储在我的系统上崩溃.所以基本上我需要停下来查看我的所有代码和内存管理内容,找出我搞砸了的地方.代码库仍然很小(约1000行),因此这很容易实现.
不过,我对这种东西感到头疼,所以我想我会把它扔出去.我在一个Linux系统上并且已经四处乱窜valgrind
,虽然我不知道我在做什么,但它确实报告说它std::string
的析构函数是无效的.我不得不承认从谷歌搜索中获得"堆腐败"一词; 关于这类东西的任何通用文章也将受到赞赏.
(之前rm -rf ProjectDir
,在C#再做一次:D)
编辑:我还没有说清楚,但我要求的是诊断这些记忆问题的建议.我知道std :: string的内容是正确的,所以这是我做过的事情(或者是一个bug,但是选择不是问题).我确信我可以查看我编写的代码,你很聪明的人会立即看到问题,但我想将这种代码分析添加到我的'工具箱'中,就像它一样.
有没有办法使用new
关键字在堆栈(ala alloca
)而不是堆(malloc
)上分配?
我知道我可以自己破解但是我不愿意.
对于我正在研究的操作系统,我正在设计内核(我将实际上称之为"核心"只是为了与众不同,但它基本相同).如果我无法完成多任务,内存管理和其他基本操作,那么操作系统本身的细节就无关紧要了,所以我需要先解决这个问题.我有一些关于设计malloc例程的任务.
我认为malloc()要么是内核本身的一部分(我倾向于这个),要么是程序的一部分,但是我将不得不编写自己的C标准库实现方式,所以我写了一个malloc.在这方面我的问题实际上相当简单,C(或C++)如何管理它的堆?
我在理论类中一直被教导的是,堆是一个不断扩展的内存块,从指定的地址开始,并且在很多方面表现得像堆栈一样.通过这种方式,我知道在全局范围内声明的变量在开头,并且更多的变量被"推"到堆上,因为它们在各自的作用域中声明,超出作用域的变量只留在内存空间中,但是该空间被标记为空闲,因此如果需要,堆可以扩展更多.
我需要知道的是,C实际上如何以这种方式处理动态扩展堆?编译的C程序是否自己调用malloc例程并处理自己的堆,还是需要为它提供自动扩展的空间?另外,C程序如何知道堆的开始位置?
哦,我知道相同的概念适用于其他语言,但我希望任何示例都在C/C++中,因为我对这种语言最为满意.我也不想担心其他事情,比如堆栈,因为我认为我能够自己处理这样的事情.
所以我想我真正的问题是,除了malloc/free(处理获取和释放页面本身等)之外,程序是否需要操作系统提供其他任何东西?
谢谢!
编辑我更感兴趣的是C如何使用malloc与堆相关而不是在malloc例程本身的实际工作中.如果它有帮助,我在x86上这样做,但C是交叉编译器所以它应该没关系.^ _ ^
进一步编辑:我理解我可能会对术语感到困惑.我被教导说"堆"是程序存储诸如全局/局部变量之类的东西.我习惯于在汇编编程中处理"堆栈",我只是意识到我可能意味着相反.对我的一点研究表明,"堆"更常用于指代程序为自己分配的总内存,或者操作系统提供的内存页面的总数(和顺序).
那么,考虑到这一点,我如何处理不断扩大的堆栈?(看来我的C理论课有点......有缺陷.)
在学习C++(和C)时,我对堆栈分配的工作有一些特别的疑问,我无法找到解决方案:
堆栈分配是否隐式调用malloc/free函数?如果不; 它如何确保堆栈分配和堆分配之间没有冲突?
如是; C++中的堆栈分配是否也隐式调用new/delete?如是; 重载一个类的new运算符会影响它的堆栈分配吗?
它在VC++中产生了令人困惑的结果; 但由于VC++并不完全符合标准(或者我听说过),我决定在这里问一下......
我有一个对象(A),它有一个由对象(B)组成的列表.列表(B)中的对象是指针,但列表本身应该是指针吗?我正在从Java迁移到C++,但仍然没有完全习惯堆栈/堆.该列表不会在类A之外传递,只传递列表中的元素.为了以防万一,将列表本身分配在堆上是一种好习惯吗?
此外,包含列表(A)的类是否也应该在堆本身上?像列表一样,它不会被传递.
int z = 1;
z <<= 31;
z >>= 31;
printf ("%d\n",z);
Run Code Online (Sandbox Code Playgroud)
当我运行代码时z=-1
,为什么?