【问题标题】:C++: vector<string> *args = new vector<string>(); causes SIGABRTC++: 向量<字符串> *args = 新向量<字符串>();导致 SIGABRT
【发布时间】:2011-06-28 12:47:40
【问题描述】:

非常不言自明。这是导致“新向量”行出现 SIGABRT 的方法:

vector<string> * Task::arguments() {
    vector<string> *args = new vector<string>(); // CAUSES SIGABRT
    int count = sizeof(_arguments);
    for (int x = 0; x < count; x++) {
        string argument(_arguments[x]);
        args->push_back(argument);
    }
    return args;
}

请注意,我在其他地方调用该行没有任何问题。以下是 Task 类中包含的列表:

#include <vector>
#include <unistd.h>
#include <string>
using namespace std;
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>

有什么想法吗?

【问题讨论】:

  • 为什么要动态分配std::vector?您几乎肯定应该使用局部变量并按值返回它。
  • 如果你真的必须使用using namespace std;。把它放在 所有包含指令之后。
  • 主要问题是 sbi 在他最初的评论中的语气表明他并没有足够关心在他假设事情之前真正了解发生了什么。认真对待这个答案是我的错,但这并不能原谅他张贴一个傲慢的断章取义的答案。然而问题已经解决了,我愿意原谅和忘记;我只敦促人们不要做出假设或断章取义的答案,尤其是对于那些“声誉很高”的人——人们会认真对待你的答案,所以不要用基于错误假设的回应来引导人们进行疯狂追逐。

标签: c++ new-operator stdvector sigabrt


【解决方案1】:

这段代码没有真正的错误,尽管样式表明您迫切需要good C++ book

正如@James 在他对该问题的评论中所说,使用 动态分配 向量对象几乎肯定是错误的,不保留它肯定是错误的智能指针
如果您在代码的其他地方也这样做了,那么您很可能搞砸了堆,这是我能想到的唯一一种情况,new 会崩溃.

【讨论】:

  • 在下面检查我的答案 - 如果这样做是错误的,那么 C++ 设计人员甚至比我想象的还要困惑......
  • @jfm:我们不会为了技术准确性而调整答案。你们必须自己解决这个问题。
  • 我永远不能将此作为答案,而是用户的个人假设。我们非常不幸的是,一个享有如此高声誉的人发布了如此断章取义的回复。我相信,这篇文章中所写的内容实际上作为设计指南是正确的,但不是有意的,也不应该被视为解决这个特定问题的方法。
【解决方案2】:

int count = sizeof(_arguments); 看起来很可疑。

sizeof 为您提供以字节为单位的大小,而不是数组元素的数量(除非每个元素正好是一个字节,即 char)。

干杯,

【讨论】:

  • 完全正确;这正是问题所在(正如我在其他答案中已经说过的那样,但很高兴看到有人真正回答了这个问题!)向你致敬,先生。 :)
【解决方案3】:

好的,事实证明问题不在于向量分配,而在于 for() 循环内部。用适当的 do/while 循环替换它可以修复它。 GDB 只是对错误的位置感到困惑,并将其卡在矢量线上……呃。不过考虑到 STL 的使用,这并不奇怪。

另外,对于那些说动态分配向量会弄乱堆的人 - 为什么?这没有任何意义;我不在乎是否动态分配每个对象;这样做不应该引起问题。过去混合堆和堆栈对象给我带来了很多问题;我能让事情始终如一地工作的唯一方法是使用所有堆对象。

如果有人能解释堆栈和堆对象如何共存,我会很高兴听到它,因为它们从来没有为我一起工作过。 Objective-C 非常有意义,而 C++ 对对象的无意义处理几乎总是会导致问题。不幸的是,我们需要使用 C++,所以我没有太多选择……

【讨论】:

  • 1) 我看不出 for 循环有什么问题。你能详细说明一下吗? 2)没有人说使用动态向量会弄乱堆。但是,这样做的每个人都是愚蠢的。 3)如果所有对你没有意义的事情确实是荒谬的,那么这个世界将是一个愚蠢的请求。幸运的是,事实并非如此。 3)我建议您搜索解释使用动态分配对象的问题。我敢肯定它之前被问过很多次。 (如果您找到的答案首先不是说尽可能首选堆栈对象,那么这些答案是错误的。)
  • 正如其他 cmets 所提到的,它只是糟糕的风格。至少您应该将字符串作为传递引用返回,例如 arguments(vector *retval),并且可能使用 retval->swap(my_vec) 作为返回它的快速方法。动态分配没有错——你应该避免返回分配对象的模式。我建议初学者阅读“Effective C++”。
  • for 循环失败,因为 _arguments 是一个字符**,所以 sizeof(_arguments) 只返回 8(或在过时的 32 位系统上为 4)而不是数组的大小。由于它是空终止的,我只使用了一个 do-while 直到结果为空。
  • 1) 好吧,我们没有看到_arguments,所以我们无法推理。 2) 在手动管理动态分配的资源时,很可能会出错,从而弄乱堆栈。弄乱堆栈是我在 20 年的 C++ 中看到的 new 崩溃的唯一原因。 3) 在 C++ 中,你 pass arguments per reference, and const, if possible总而言之,你是从一个非常无知的 POV 看待 C++,而不认为你的无知限制了你的判断能力。 学习,而不是判断。
  • 如果这里有什么傲慢的话,那是你最后的断言:你基本上说过,“如果你刚刚问我是否犯了错误,我本可以告诉你我没有犯错”吨。”真的吗?我希望我能确定我是否犯了错误。 @sbi 是对的:如果您尝试在一个重要的 C++ 程序中手动管理内存,那么几乎可以肯定您的代码中某处有错误。这些问题可能不会很明显,并且很长一段时间都不会表现为可观察到的错误,但它们几乎肯定存在。
【解决方案4】:

在您执行此调用之前,可能有其他东西损坏了堆。您是否尝试过在 valgrind 或同等工具下运行?

【讨论】:

  • 我不需要 - 事实证明它在这一行显示错误只是因为 GDB 对错误的实际位置感到困惑。这实际上是我能够修复的 for() 循环中的一个逻辑错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-27
  • 2011-03-01
相关资源
最近更新 更多