社区首页 >问答首页 >大型数组、std::vector和堆栈溢出

大型数组、std::vector和堆栈溢出
EN

Stack Overflow用户
提问于 2016-05-25 04:40:51
回答 3查看 4.5K关注 0票数 18

我有一个从大型数组中读取数据的程序,我最初在Visual Studio中将该程序划分为两个单独的项目,每个项目都工作得很好,但当我试图将它们放在一起时,程序表现得很奇怪,在调试时跳过了一些步骤。我对C++非常陌生,所以我开始做一些研究,我发现也许我是在用那些巨大的数组来填充堆栈,我应该试着把它们放到堆上。

我决定更改std::vector的每个数组,并以这种方式初始化它们:

代码语言:javascript
代码运行次数:0
复制
std::vector<double> meanTimeAO = { 0.4437, 0.441, 0.44206, 0.44632, 0.4508, 0.45425,...}

但是现在当我尝试编译编译器崩溃时,当我尝试编译堆栈溢出时更改了所有的数组后,我认为我通过将数组更改为向量来释放堆栈中的内存空间,但似乎我得到了相反的结果,为什么呢?

我该如何处理这些大数组呢?(它们是固定的,不会改变值或大小)

EN

回答 3

Stack Overflow用户

发布于 2016-05-25 07:59:56

正如@Ajay的回答和@Cornstalks注释正确指出的那样,通过在数组上使用staticconstexpr限定符,可以完全避免堆栈和堆

代码语言:javascript
代码运行次数:0
复制
const static std::array<float, 1000000> a1 = {}; // OK
constexpr    std::array<float, 1000000> a2 = {}; // OK in C++11 onwards

这会将数组存储在内存的data initialized部分(good explanation here)。const仅用于禁止修改a1,并不是避免堆栈溢出所必需的。声明为constexpr的变量也会自动为const,因此不需要限定符。

注意:您也可以通过使数组成为全局变量来实现static的效果,尽管我不建议这样做。

程序堆栈溢出

如果您的数据是非静态的,那么当元素数量非常大时,您应该使用std::vector (或其他类型的堆分配的内存)。

代码语言:javascript
代码运行次数:0
复制
std::array<float, 1000000> a = {};   // Causes stack-overflow on 32-bit MSVS 2015
std::vector<float> v(1000000);       // OK

这是因为默认堆栈大小约为1MB,100万个浮点数需要约4MB。堆的大小受系统可用内存(RAM)的限制。More on the stack and heap here

std::vector的缺点是它比std::array慢一点(堆内存分配、释放和访问都比堆栈慢),而且它的大小不是固定的。但是,您可以将std::vector声明为const,以防止自己(或其他人)意外更改其大小或元素。

代码语言:javascript
代码运行次数:0
复制
const std::vector<float> v = {...}; 

现在,为什么你的std::vector会导致堆栈溢出还是个谜。然而,当std::vector在堆上分配它的元素时,它也在堆栈上分配一个指针(32位上为4字节,64位上为8字节)。因此,如果一次拥有超过250,000个std::vector,这也会导致堆栈溢出(在64位系统上为大约125,000)。

编译器堆栈溢出

像任何程序一样,编译器分配内存-其中一些内存将在堆栈上。MSVC上编译器堆栈溢出的官方错误是Fatal Error C1063

鉴于您的调试器行为异常,我的建议是尝试通过手动将代码拆分成模块化单元并单独编译来隔离有问题的代码。有可能是因为少量的代码消耗了大量的堆栈,例如通过递归生成大量的函数。

或者,您的代码可能本质上非常复杂,因此它自然需要比堆栈拥有的内存更多的内存。在这种情况下,拆分代码仍然是有好处的,但您也可以尝试使用increasing the default stack size of MSVC

改进你的代码

为了改进你的代码,你可以试着把你的数据分成块。例如,您可以:读入大约256KB的数组,处理它,将数组写回文件,然后移到下一个256KB。您可以进一步选择块的大小小于L1缓存的大小(以便可以一次存储所有数据),这将通过最小化缓存未命中来提高性能。

备注

  1. MSVS 2015 (更新2)在编译时产生内部编译器错误

#include "stdafx.h“#include int main() { constexpr std::array a= {};return 0;}

static const变体运行得很好,如果我将a移出main (使其成为全局变量),那么它也会运行得很好。

  • 没有chkstk.asm是不寻常的。我的网站是C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\crt\src\i386\chkstk.asm。如果你错过了它,也许可以尝试重新安装MS Visual Studio.
票数 11
EN

Stack Overflow用户

发布于 2016-05-25 05:07:13

如果数组的大小是固定的,并且它的元素没有变化,那么实际上就没有必要使用vector。您可以使用std::arrayconst的数组或constexpr

代码语言:javascript
代码运行次数:0
复制
constexpr float meanTimeAO[] = { 0.4437f, 0.441f, 0.44206f, 0.44632f, 0.4508f, 0.45425f,...}
票数 9
EN

Stack Overflow用户

发布于 2016-05-25 10:44:35

指出上述答案中可能忽略的几个问题:

  1. “程序在调试时跳过了一些步骤”。OP,你能提供更多关于你的意思的细节吗?也许,您正在调试一个发布版本,并且当您单步执行代码时,您观察到正在执行的代码行并不是您期望下一步执行的代码行(这对于使用编译器的发布版本来说是完全正确的行为optimisations).
  2. The问题指出编译器因堆栈溢出而崩溃。而不是执行的程序。所以这个问题是一个编译器的问题。当然,更改代码可能会使编译器不会崩溃,但上面关于在堆栈上分配std::vector的注释与可能导致编译器崩溃的原因无关。

建议:您可以尝试查看您正在使用的编译器版本中是否有任何已知的错误(即查看您的编译器供应商是否发布了可能解决编译器崩溃问题的更新版本)。

此外,特别要注意“它们永远不会改变值或大小”的注释,尝试将数据放入静态常量双数组,而不是std::vectors (甚至是链表)中。一个不变的静态分配的只读链表是一种浪费时间的行为,而你可能只应该使用double[]。静态常量数据在编译/链接时初始化,而不是在运行时初始化,并且存在于它自己的内存区(严格地说,既不是堆栈也不是堆)。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37427967

复制
相关文章
Hibernate @OneToMany 及 @Cascade级联操作
由此,就会使用级联操作,在一对多关系中,@Cascade属性(级联)只设置“一”的一方即可,外键由“多”的一方进行维护。
好好学java
2020/03/16
6.1K0
Hibernate @OneToMany 及 @Cascade级联操作
Java 多重选择结构
多重选择结构是一种程序控制结构,它允许程序在多个条件之间进行选择,并执行相应的操作。它使用一系列的if-else语句,以及一个或多个switch语句,以便在多个条件之间进行选择。
久绊A
2023/03/24
3550
对象持久化API之JPA入门教程
注意:JPA是规范,不是ORM框架,是ORM框架的规范,JPA没有实现ORM,具体实现由ORM厂商提供
SmileNicky
2019/01/17
1.1K0
JPA系列之对象持久化API JPA简介
注意:JPA是规范,不是ORM框架,是ORM框架的规范,JPA没有实现ORM,具体实现由ORM厂商提供
SmileNicky
2022/05/07
8360
JPA系列之对象持久化API JPA简介
Hibernate学习笔记 多表映射
前面说了Hibernate的单表映射,由于是实体类和数据表之间一对一的映射,所以比较简单。现在就来说说多表映射,这需要涉及到多个实体类和数据表之间的关系。因此稍微复杂一点。
乐百川
2022/05/05
1.6K0
【Hibernate】Hibernate框架配置详解
通过Hibernate我们可以方便地操作数据库读取出来的信息,减少了繁琐的JDBC操作。
陈树义
2022/04/29
1.4K0
JPA关系映射系列三:one-to-many和many-to-one
本篇文章引导你通过Spring Boot,Spring Data JPA和MySQL实现one-to-many和many-to-one关联映射。
java干货
2021/02/17
9890
Hibernate Annotation (Hibernate 注解)
英文:http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/
Hongten
2018/09/18
1.4K0
Hibernate检索策略
Hibernate的检索策略可以通过配置文件或注解来定义。以下是Hibernate中常用的几种检索策略:
堕落飞鸟
2023/05/16
4700
碎片化 | 第四阶段-56-ManyToOne和OneToMany映射关系-视频
http://v.qq.com/x/page/f0567zgfet1.html ManyToOne (多对1) 表结构: note表----usernote表----(多对1) 1:将usernote实体类进行hibernate映射 2:在note实体类中,增加属性值和注解,并将原有userId属性注释 @ManyToOne @JoinColumn(name="userId") private Usernote usernote; 3:修改listDetail.jsp文件
码神联盟
2018/04/03
9070
Hibernate关联关系
文章目录 1. Hibernate关联关系 1.1. 一对一 1.1.1. 背景 1.1.2. 准备 1.1.3. 单向外键关联 1.1.3.1. 通过丈夫访问妻子 1.1.3.2. 通过妻子访问丈夫 1.1.3.3. 总结 1.1.4. 双向外键关联(@OneToOne(mappedBy=””) 1.1.4.1. 问题 1.1.4.2. 解决办法 1.1.4.3. 实现 1.1.4.4. 测试 1.2. 一对多 1.2.1. 准备 1.2.2. 前提须知 1.2.3. 单向外键关联 1.2.3.1.
爱撒谎的男孩
2019/12/31
6.3K1
如何在 Spring Boot 中 读写数据
写在前面:2020年面试必备的Java后端进阶面试题总结了一份复习指南在Github上,内容详细,图文并茂,有需要学习的朋友可以Star一下! GitHub地址:https://github.com/abel-max/Java-Study-Note/tree/master
用户5546570
2020/09/28
15.9K0
如何在 Spring Boot 中 读写数据
hibernate的关联与级联
1、关联指的是类之间的引用关系。如果类A与类B关联,那么被引用的类B将被定义为类A的属性。 2、关联的分类:关联可以分为一对一、一对多/多对一、多对多关联
全栈程序员站长
2022/08/04
1.3K0
hibernate的关联与级联
JPA 注解学习
最近学习hibernate注解形式配置POJO类,将注解的解析记下来,以备以后使用。
一个会写诗的程序员
2018/08/17
2.9K0
Hibernate
一、什么是 Hibernate? Hibernate 是一个基于元数据的轻量级的 ORM 框架: 1、元数据(Meta Data):data about data(数据的数据),也就是说描述一个对
用户2038009
2021/03/08
1.3K0
Spring 全家桶之 Spring Data JPA(四)
只配置了客户到联系人的关系,查看执行的SQL,相比上一次测试多了一条update外键的sql语句
RiemannHypothesis
2022/08/19
1.6K0
Spring 全家桶之 Spring Data JPA(四)
Hibernate的入门(Hibernate的环境搭建、Hibernate的API)
Hibernate第一天(Hibernate的环境搭建、Hibernate的API、Hibernate的CRUD)
AlbertYang
2020/09/08
1.2K0
Hibernate的入门(Hibernate的环境搭建、Hibernate的API)
ssh搭建开发环境
公司一直不是ssh零配置的框架,每次写action都要在applicationcontext和struts里面配置,好麻烦,最近有空,写了一个ssh零配置的框架 这里写了一个小的项目,以用户权限管理为例 先做准备工作: 1.struts2去官网下载最新版struts开发包http://struts.apache.org/download.cgi#struts216 2.hibernate4去官网下载最新版hibernate4开发包http://sourceforge.net/projects/hiberna
xiangzhihong
2018/01/29
2.1K0
Hibernate配置access Hibernate 连接 access
个人测试结果,还是使用方法一比较妥当。方法3出现了一个奇怪错误~~ 1、Hibernate对于Access的支持 方法一: 下载两个jar包,一个是Access的JDBC驱动包;另一个是数据库方言包,里面有支持Access方言的类。 下载地址:http://www.hxtt.com/access.zip,http://www.hxtt.com/test/hibernate.zip。 配置如下:(URL那里可以使用相对路径) xml 代码 <property name="hibernate.dialec
用户1258909
2018/07/03
2.3K0
Hibernate 的应用(Hibernate 的结构)?
SessionFactory sessionFactory = new Configuration().configure().
MickyInvQ
2020/09/27
7490

相似问题

@OneToMany in hibernate

63

Hibernate onetomany映射

26

Hibernate,OneToMany,AnnotationException

35

Hibernate OnetoMany关系

11

Hibernate @OneToMany关系

21
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文