【问题标题】:SIGABRT when returning from a function?从函数返回时的SIGABRT?
【发布时间】:2020-09-22 09:32:39
【问题描述】:

我是 C++ 新手,来自 python/kotlin 背景,所以在理解这里的幕后发生的事情时遇到了一些麻烦......

问题

我使用所需参数调用calculateWeights(公共)方法,然后调用一系列方法,包括conjugateGradientMethod(私有),并且应该返回一个双精度向量。 conjugateGradientMethod 将双精度向量返回到 calculateWeights 就好了,但 calculateWeights 不会将其返回给它的调用者:

代码

calculateWeights 的调用点:

        Matrix cov = estimator.estimateCovariances(&firstWindow, &meanReturns);

        cout << "before" << endl; // this prints
        vector<double> portfolioWeights = optimiser.calculateWeights(&cov, &meanReturns);
        cout << "after" << endl; // this does not print

这里是calculateWeights:

vector<double> PortfolioOptimiser::calculateWeights
        (Matrix *covariances, vector<double> *meanReturns) {

    vector<double> X0 = this->calculateX0();
    Matrix Q = this->generateQ(covariances, meanReturns);
    vector<double> B = this->generateB0(); 

    vector<double> weights = this->conjugateGradientMethod(&Q, &X0, &B);

    cout << "inside calculateWeights" << endl;
    print(&weights); // this prints just fine
    cout << "returning from calculateWeights..." << endl; // also prints

    return weights; //this is where the SIGABRT shows up

输出

输出看起来像这样(我已经检查过了,它输出的权重在数字上确实是正确的):

before
inside calculateWeights
1.78998
0.429836
-0.62228
-0.597534
-0.0365409
0.000401613
returning from calculateWeights...

然后什么都没有。

我很欣赏这是不理想的 printf 调试,因此我使用 Cion 的调试器找到以下内容:

当我使用 CLion 的调试器时

我在 conjugateGradient 方法和 calculateWeights 方法的返回值上设置了一个断点。调试器通过第一个就好了。在我跨过 calculateWeights 的返回后,它向我显示了一个 SIGABRT,并出现以下错误:

Thread 1 "markowitzportfoliooptimiser" received signal SIGABRT, Aborted.
__gnu_cxx::new_allocator<std::vector<double, std::allocator<double> > >::deallocate (this=0x6, __p=0x303e900000762) at /usr/lib/gcc/x86_64-pc-cygwin/9.3.0/include/c++/ext/new_allocator.h:129

这可能是错误的,但我第一次尝试理解是我已经超出了vector&lt;double&gt; weights 的大小?它只有 6 双倍长,在下面的循环之后我从不附加任何东西。这就是它在conjugateGradientMethod 内部的创建方式:

如何在conjugateGradientMethod中创建权重

    vector<double> weights= vector<double>(aSize);
    for (int i = 0; i < aSize; i++) {
        weights[i] = aCoeff * a->at(i) + bCoeff* b->at(i);
    }


我尝试过的事情

  1. 初始化calculateWeights 中的双权重向量并将指向它的指针传递给conjugateGradientMethod。结果相同。
  2. calculateWeightsconjugateGradientMethod 类上都有一个公共属性,并让它为其分配权重(因此两个函数都返回 void)。结果相同。

更一般地说,我之前在传递两个函数的返回值时遇到过这种问题。 (如果这有意义?)即从私有方法到公共方法,再到公共方法的调用点。

如果在这种情况下对 SIGABRT 提供任何建议,我将不胜感激,我读过它是在 abort() 向调用进程发送 SIGABRT 信号时,但我不确定如何在此示例中使用它。

另外,我对任何其他有助于在未来避免这种情况的风格/最佳做法都充满信心

编辑:找到解决方案

经过大量工作后,我安装并运行了 Ubuntu 20.04 LTS,因为我无法让 Address Sanitizer 和 Valgrind 在 Windows 10 上通过 WSL 工作(第一次在 Linux 上 - 我有点喜欢它)。

现在使用 Address Sanitizer,我可以看到我在两个独立帐户的双精度向量中写入了太多元素,与 @Lukas Matena 正确发现的 weights 向量无关。令人困惑的是,这早在它到达上面的 sn-ps 之前。

如果将来有人发现这个,这些对我有很大帮助:

Heap Buffer Overflow

Heap vs Stack 1

Heap vs Stack 2

【问题讨论】:

  • 我看不出这些 sn-ps 有什么问题。我的猜测是某个地方的堆栈损坏,以某种方式恰好触发调用abort() 的断言失败。如果您的编译器支持,请尝试启用 AddressSanitizer,或者在 valgrind 下运行。
  • 看来你是在 Linux/Unix 下,安装 valgrind 并用它运行你的程序,它会提示你无效的内存访问/释放/删除/...
  • 明智的选择是您的代码中有未定义的行为。第一步,在这种情况下……您是否完全打开了编译器警告并解决了所有问题? (感谢我在打字时输入的评论,是的,在 valgrind 中运行你的程序,它会带你犯错误)
  • 感谢大家的快速回复。我正在通过 cygwin 安装 g++ 的 Windows 电脑上运行。我目前正在为 Windows 上的 clion 安装并找出 valgrind。我刚刚打开了编译器警告,我看到的唯一警告与未使用的变量有关[对于我即将实现的功能]。再次感谢大家。
  • 原来我使用的 CLion 版本(或更新版本)有一个错误,因为我在 PC 上,所以不允许 valgrind 所需的 WSL:youtrack.jetbrains.com/issue/CPP-11852 我现在到地址消毒剂...

标签: c++ function return clion sigabrt


【解决方案1】:

错误消息说当calculateWeights 即将返回时,它未能释放std::vector&lt;double&gt;。这可能意味着函数中至少有一个局部变量(此时正在被销毁)已损坏。

您似乎专注于weights,但由于您提到的尝试都失败了,我宁愿怀疑X0Bweights 可能由于返回值在那时甚至没有被释放优化)。

你可以尝试的事情:

  • 开始使用其他人建议的地址清理工具
  • 注释掉部分代码,看看它是否能让你更接近(换句话说,做一个最小的例子)
  • 将其中一个向量设为成员变量,这样它就不会在此时被破坏(不是修复方法,但它可能会提供关于谁是罪犯的线索)

您可能在某个地方对相应的向量做了坏事,可能在calculateX0generateB0(您尚未共享)。它可能是向量的delete-ing 部分,返回对临时而不是副本的引用等。return 的 SIGABRT 是你被抓到的地方,但内存损坏问题通常比它们出现得晚造成的。

(我本来可以把它缩短并作为评论发布,但作为新手我不能。希望它可以算作“在这种情况下对 SIGABRT 的建议”,这实际上是人们要求的)。

【讨论】:

  • 谢谢朋友,我现在正在研究其他功能,带有地址消毒剂
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-07-04
  • 1970-01-01
  • 2016-08-28
  • 2013-03-31
  • 1970-01-01
  • 2012-05-25
  • 1970-01-01
相关资源
最近更新 更多