我可以通过在堆上生成对象来溢出堆栈吗?

时间:2015-05-20 17:51:25

标签: c++

让我们看一下这个简单的例子:

Angel.hh

#include <string>

class Angel
{
  public :

  Angel( std::string n
       , std::string l )
  : name(n)
  {
    location = new std::string(l);
    int i;
    for(i=0;i<10;i++)
    {
      nbrOfFeathers+=i*i;
    }
  };

  ~Angel(  )
  {
    delete location;
  };

  std::string name;
  std::string* location;
  int nbrOfFeathers;
};

main.cc

#include "Angel.hh"
#include <iostream>

int main(  )
{
  std::string locationA( "Pandemonium" );
  std::string locationB( "Purgatory" );

  Angel angel1( "Angel of Death" , locationB );
  std::cout << angel1.name << " is in " << *angel1.location << std::endl;

  Angel* angel2 = new Angel( "Angel of the Apocalypse", locationA );
  std::cout << angel2->name << " is in " << *angel2->location << std::endl;

  delete angel2;
}

我们可以看到angel1存储在堆栈中,而angel2存储在堆上。如果我只读取标题(Angel.hh),我认为name将存储在堆栈中,而location将存储在堆上。

我想知道我断言的是真的。因为我在脑海中首先使用堆栈而不是生命周期短的变量,例如整数i,并且最好不要在应用程序运行时间内使用堆栈来增加数量。如果我的断言是真的,我可以通过在堆上产生天使来溢出堆栈(因为name)?存储i的地方?

¹在这种情况下并不重要,这只是一个例子......

2 个答案:

答案 0 :(得分:2)

让我更详细地说明你的情况 - 记忆明智:

Angel

在此代码中,整个Angel结构位于堆栈中。这不包括Angel中也可能分配给堆的代码(如果它包含已分配的指针等),但Angel* angel2 = new Angel( "Angel of the Apocalypse", locationA ); std::cout << angel2->name << " is in " << *angel2->location << std::endl; 内声明的所有内容都在堆栈中。

Angel

这里,只有指向Angel的指针存在于堆栈中,但->类/结构的全部内容都存在于堆上。请注意,我们必须使用std::string name; std::string* location; int nbrOfFeathers; 运算符来访问结构。这意味着我们使用指针来获取堆上的数据。详细说明:

for i in range(0,len(file_count)):
    #Source folder with original files
    os.chdir(path+'\\'+folder_source_location)
    #Generate file names
    file_name = file_source_begin+("%0"+str(ndigit)+"d") % file_count[i]+"_tec.dat"

    #Read the file
    Data = read_tecUNS(file_name)

    #New data set modified
    Data_new = Data

    #Translation
    Data["node"]["X"]+=translator_plane2RotCenter[0]    #The += is important or the Data won't be affected by the translation
    Data["node"]["Y"]+=translator_plane2RotCenter[1]
    Data["node"]["Z"]+=translator_plane2RotCenter[2]

    #Rotation
    Y_temp = Data["node"]["Y"]*cos(theta_rot_rad)-Data["node"]["Z"]*sin(theta_rot_rad)
    Z_temp = Data["node"]["Y"]*sin(theta_rot_rad)+Data["node"]["Z"]*cos(theta_rot_rad)

    Data_new["node"]["Y"]=Y_temp
    Data_new["node"]["Z"]=np.mean(Z_temp)   #Due to rounding, the Z values are not exactly the same. The mean avoid that.

    #Write the new file
    os.chdir(path+'\\'+folder_source_location+'\\'+"Output")
    write_tecplot(file_name,Data_new)

将分配给Angel2中的堆。

我希望这能为你解决一些问题。

答案 1 :(得分:1)

  

如果我只读取标题(Angel.hh),我认为名称将存储在堆栈中,而位置将存储在堆上。

但是你知道这会是错的,所以不要这么想!相反,您应该认为name将嵌入Angel对象中,无论它在何处构建。

  

因为我在脑海中首先使用堆栈而不是生命周期短的变量,例如整数i,并且最好不要在应用程序运行时间内使用堆栈来增加数量。< / p>

这是一个很好的经验法则。对于面向PC的操作系统和C ++环境,堆栈的大小通常默认为1到8MB,因此任何数据进入数十亿字节,甚至是递归函数堆栈上的更小数据,最好动态分配(使用{{ 1}},或者将元素存储在为您管理动态内存的标准库容器中。

  

如果我的断言是真的,我可以通过在堆上产生天使来溢出堆栈(因为名称)吗?我存放在哪里?

否 - 如上所述,断言是错误的:当你new new时,动态分配Angel并且你不能溢出堆栈。基本上,堆栈仅用于自动解析的自动局部变量,以及作为函数退出的内存回收,甚至更多本地范围,如namefor (...) { }while (...) { },{{ 1}}或函数内的普通旧do { } while (...);