C++:vector<string> *args = new vector<string>(); 导致 SIGABRT

3
相当容易理解。这是导致“新向量”行出现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类中包含的列表:
请注意,在其他地方我调用了那一行而没有任何问题。这是Task类中包含的包含列表:
#include <vector>
#include <unistd.h>
#include <string>
using namespace std;
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>

有什么想法吗?

11
为什么要动态分配std::vector?你几乎肯定应该使用一个局部变量并通过值返回它。 - James McNellis
4
如果你真的必须使用 using namespace std;,请将它放在所有包含指令之后。 - Benjamin Lindley
请参见https://dev59.com/HlTTa4cB1Zd3GeqPs4GF。 - Robert Harvey
1
主要问题在于sbi在他最初的评论中的语气表明他并没有足够关心实际情况就假设事情。是我的错,我认真对待了那个答案,但这并不能为他发布一个傲慢的脱离上下文的回答开脱。然而,问题已经解决,我愿意原谅和忘记;我只敦促人们不要做出假设或脱离上下文的回答,特别是对于那些声誉高的人-人们认真对待你的回答,所以不要基于错误的假设引导人们进入一场野鸭追逐战。 - jstm88
4个回答

6

这段代码实际没有错误,虽然代码风格表明你急需一本好的C++书籍

正如@James在评论中提到的,几乎肯定不能使用动态分配的向量对象,而且不将其保留在智能指针中肯定是错的。
如果在您的代码中也有这样的情况,那么非常可能破坏了堆内存,这是我唯一想到会导致new崩溃的情况。


请检查我的答案,如果这样做是错误的,那么C++的设计者比我想象的还要困惑得多... - jstm88
1
@jfm:我们不会对技术准确性进行审核。你们必须自己解决这个问题。 - Robert Harvey
我永远不会把这当作答案,而是用户个人的假设。我们非常不幸,一个声誉如此高的人发布了这样一个脱离上下文的回复。我相信,这篇帖子中所写的确实是一份设计指南,但并不意味着它是解决这个特定问题的方案,也不应该被赞赏。 - Ayan Sengupta

3

好的,事实证明问题并不在于向量分配,而是在for()循环内部。用适当的do/while循环替换它可以解决问题。GDB只是对错误位置感到困惑,并将其粘贴到了向量行上...唉。考虑到使用STL,这并不令人惊讶。

此外,对于那些说动态分配向量可能会破坏堆栈的人——为什么?这没有任何意义;我不在乎是否动态分配每个对象;这样做不应该导致问题。在过去,混合堆栈对象已经给我带来了很多问题;我能够使事情始终正常工作的唯一方法就是使用所有堆对象。

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


正如其他评论中提到的那样,这只是一种不好的风格。至少你应该将字符串作为引用传递返回,例如参数(vector<string> *retval),并且可以使用retval->swap(my_vec)来快速返回它。动态分配没有问题 - 你只需要避免返回已分配的对象的模式。我建议初学者阅读《Effective C++》。 - John Ripley
1
for循环失败是因为_arguments是char **,所以sizeof(_arguments)只返回8(或在过时的32位系统上返回4),而不是数组的大小。由于它是以null结尾的,所以我使用了do-while直到结果为null。 - jstm88
另外,约翰,我不确定在这种情况下交换的目的是什么。我有指向原始数组的现有指针,需要在返回新数组后保持有效;交换内容是行不通的。此外,将返回值传递给指针参数只应在极少数情况下进行;只有在非常少的情况下才应该使用那种“风格”。它只会导致混乱的代码,并且在我之前尝试类似操作时,这是另一件引起无数问题的事情。 - jstm88
3
  1. 好的,我们没有展示“_arguments”所以我们无法推理它。
  2. 当手动管理动态分配的资源时,可能会出现错误,这会破坏堆栈。在我20年的C++经验中,破坏堆栈是导致new崩溃的唯一原因。
  3. 在C++中,您需要通过_reference_传递参数,并在可能的情况下使用“const”。总而言之,如果不考虑自己的无知会限制您的判断能力,那么您正在从非常无知的角度来看待C++。请先学习,而不是评判。
- sbi
1
如果这里有任何傲慢的话,那就是你最后的断言:你基本上说,“如果你只是问我是否犯了错误,我本可以告诉你我没有。” 真的吗?我希望我能对自己是否犯了错误如此确定。@sbi是正确的:如果你试图在一个非平凡的C++程序中手动管理内存,几乎可以肯定你的代码中有错误。这些问题可能不会很明显,并且可能不会表现为可观察到的错误很长一段时间,但它们几乎肯定存在。 - James McNellis
显示剩余6条评论

3

int count = sizeof(_arguments); 这句话看起来有点可疑。

sizeof 给出的是字节数,而不是数组中元素的数量(除非每个元素恰好占用一个字节,例如 char)。

祝好!


没错,那正是问题所在(正如我在另一个答案中已经说明的那样,但很高兴看到有人真正回答了这个问题!)向您致敬,先生。 :) - jstm88

2

可能在调用此函数之前,某些其他问题已经破坏了堆内存。你是否尝试在valgrind或等效工具下运行?


我其实不需要这么做——事实证明,GDB只是对错误的位置感到困惑,所以它在这一行显示了错误。实际上,这是一个for()循环中的逻辑错误,我已经修复了它。 - jstm88

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接