首页 > 解决方案 > EXC_BAD_ACCESS:使用 std::array 的问题

问题描述

我正在尝试将 boost 库的 odeint 与std::vectoror一起使用std::array。在这两种情况下我都没有编译问题,但是,在std::array. 下面给出的是 MWE。

我在头文件中定义了两个类:ODE1ODE2with std::vector, 和。std::arrayode.hpp

#ifndef ODE_HPP_
#define ODE_HPP_

// c++ standard library headers
#include <array>
#include <iostream>
#include <vector>

namespace ode {
constexpr size_t n_variables = 1e4;
}  // namespace ode

class ODE1 {
 public:
  ODE1(const double o) : V_(ode::n_variables, o) {}  // explicit constructor

  std::vector<double>& GetVoltage() { return V_; }

  void operator()(const std::vector<double>& Y, std::vector<double>& dYdt,
                  const double /* time */) {
    using namespace ode;
    for (size_t n = 0; n < n_variables; n++) dYdt[n] = Y[n];
  }

 private:
  std::vector<double> V_{};
};

class ODE2 {
  using Array = std::array<double, ode::n_variables>;

 public:
  // constructors
  ODE2(const double o) { V_.fill(o); }  // explicit constructor

  Array& GetVoltage() { return V_; }

  void operator()(const Array& Y, Array& dYdt, const double /* time */) {
    using namespace ode;
    for (size_t n = 0; n < n_variables; n++) dYdt[n] = Y[n];
  }

 private:
  Array V_{};
};
#endif  //   ODE_HPP_

主要功能定义在文件“ode.cpp”中

// related header
#include "ode.hpp"

// other library headers
#include <boost/numeric/odeint.hpp>

int main() {
  constexpr double abs_err = 1.0e-10;
  constexpr double rel_err = 1.0e-8;
  constexpr double sim_duration = 20.0;              // ms
  constexpr double t_start = 0;                      // ms
  constexpr double t_stop = t_start + sim_duration;  // ms
  constexpr double dt = 5e-3;                        // ms
  {
    std::cout << "ODE1\n";
    using namespace boost::numeric::odeint;
    using error_stepper_type = runge_kutta_dopri5<std::vector<double>>;

    ODE1 o(-60.0);
    integrate_adaptive(make_controlled<error_stepper_type>(abs_err, rel_err), o,
                       o.GetVoltage(), t_start, t_stop, dt);
  }
  {
    std::cout << "ODE2\n";
    using namespace boost::numeric::odeint;
    using error_stepper_type =
        runge_kutta_dopri5<std::array<double, ode::n_variables>>;

    ODE2 o(-60.0);
    integrate_adaptive(make_controlled<error_stepper_type>(abs_err, rel_err), o,
                       o.GetVoltage(), t_start, t_stop, dt);
  }
  return 0;
}

我在 macOS Big Sur (11.5.2) 上使用 clang 编译器编译如下 c++ -O0 -g -fsanitize=address -fno-omit-frame-pointer -Wall -Wextra -Wpedantic -std=c++17 ode.cpp -o ode

正如我上面提到的,我没有遇到编译问题。当我运行可执行文件时,我遇到以下问题

ODE1
ODE2
AddressSanitizer:DEADLYSIGNAL
=================================================================
==30573==ERROR: AddressSanitizer: stack-overflow on address 0x7ffee6a1e3f8 (pc 0x00010896439e bp 0x7ffee6d18610 sp 0x7ffee6a1e400 T0)
    #0 0x10896439e in unsigned long boost::numeric::odeint::integrate_adaptive<boost::numeric::odeint::controlled_runge_kutta<boost::numeric::odeint::runge_kutta_dopri5<std::__1::array<double, 10000ul>, double, std::__1::array<double, 10000ul>, double, boost::numeric::odeint::array_algebra, boost::numeric::odeint::default_operations, boost::numeric::odeint::initially_resizer>, boost::numeric::odeint::default_error_checker<double, boost::numeric::odeint::array_algebra, boost::numeric::odeint::default_operations>, boost::numeric::odeint::default_step_adjuster<double, double>, boost::numeric::odeint::initially_resizer, boost::numeric::odeint::explicit_error_stepper_fsal_tag>, ODE2, std::__1::array<double, 10000ul>, double, boost::numeric::odeint::null_observer>(boost::numeric::odeint::controlled_runge_kutta<boost::numeric::odeint::runge_kutta_dopri5<std::__1::array<double, 10000ul>, double, std::__1::array<double, 10000ul>, double, boost::numeric::odeint::array_algebra, boost::numeric::odeint::default_operations, boost::numeric::odeint::initially_resizer>, boost::numeric::odeint::default_error_checker<double, boost::numeric::odeint::array_algebra, boost::numeric::odeint::default_operations>, boost::numeric::odeint::default_step_adjuster<double, double>, boost::numeric::odeint::initially_resizer, boost::numeric::odeint::explicit_error_stepper_fsal_tag>, ODE2, std::__1::array<double, 10000ul>&, double, double, double, boost::numeric::odeint::null_observer) integrate_adaptive.hpp:40
    #1 0x10894335e in unsigned long boost::numeric::odeint::integrate_adaptive<boost::numeric::odeint::controlled_runge_kutta<boost::numeric::odeint::runge_kutta_dopri5<std::__1::array<double, 10000ul>, double, std::__1::array<double, 10000ul>, double, boost::numeric::odeint::array_algebra, boost::numeric::odeint::default_operations, boost::numeric::odeint::initially_resizer>, boost::numeric::odeint::default_error_checker<double, boost::numeric::odeint::array_algebra, boost::numeric::odeint::default_operations>, boost::numeric::odeint::default_step_adjuster<double, double>, boost::numeric::odeint::initially_resizer, boost::numeric::odeint::explicit_error_stepper_fsal_tag>, ODE2, std::__1::array<double, 10000ul>, double>(boost::numeric::odeint::controlled_runge_kutta<boost::numeric::odeint::runge_kutta_dopri5<std::__1::array<double, 10000ul>, double, std::__1::array<double, 10000ul>, double, boost::numeric::odeint::array_algebra, boost::numeric::odeint::default_operations, boost::numeric::odeint::initially_resizer>, boost::numeric::odeint::default_error_checker<double, boost::numeric::odeint::array_algebra, boost::numeric::odeint::default_operations>, boost::numeric::odeint::default_step_adjuster<double, double>, boost::numeric::odeint::initially_resizer, boost::numeric::odeint::explicit_error_stepper_fsal_tag>, ODE2, std::__1::array<double, 10000ul>&, double, double, double) integrate_adaptive.hpp:83
    #2 0x10894262c in main ode.cpp:30
    #3 0x7fff203d0f3c in start+0x0 (libdyld.dylib:x86_64+0x15f3c)

SUMMARY: AddressSanitizer: stack-overflow integrate_adaptive.hpp:40 in unsigned long boost::numeric::odeint::integrate_adaptive<boost::numeric::odeint::controlled_runge_kutta<boost::numeric::odeint::runge_kutta_dopri5<std::__1::array<double, 10000ul>, double, std::__1::array<double, 10000ul>, double, boost::numeric::odeint::array_algebra, boost::numeric::odeint::default_operations, boost::numeric::odeint::initially_resizer>, boost::numeric::odeint::default_error_checker<double, boost::numeric::odeint::array_algebra, boost::numeric::odeint::default_operations>, boost::numeric::odeint::default_step_adjuster<double, double>, boost::numeric::odeint::initially_resizer, boost::numeric::odeint::explicit_error_stepper_fsal_tag>, ODE2, std::__1::array<double, 10000ul>, double, boost::numeric::odeint::null_observer>(boost::numeric::odeint::controlled_runge_kutta<boost::numeric::odeint::runge_kutta_dopri5<std::__1::array<double, 10000ul>, double, std::__1::array<double, 10000ul>, double, boost::numeric::odeint::array_a
==30573==ABORTING
zsh: abort      ./ode

n_variables奇怪的是,当我将标头中的参数 , 从 10000 更改为 1000时,我没有遇到问题。

此外,我曾经lldb调试过这个问题,它似乎是stop reason = EXC_BAD_ACCESS (code=2, address=0x7ffeef3fbc58)

我不太确定这里的问题是什么!任何帮助将不胜感激。

标签: c++c++17stdvectorstdarray

解决方案


ASAN 增加了程序所需的堆栈内存量,而您的程序已经需要很多。增加堆栈大小限制:

$ ulimit -s 81920
$ ./ode
ODE1
ODE2
$

推荐阅读