【问题标题】:Segmentation fault error C++分段错误错误 C++
【发布时间】:2018-04-13 00:39:57
【问题描述】:

我正在编写一个简单的程序,将两个向量和 push_backs 交替转换为第三个向量,但是我得到一个分段错误错误(核心转储)。我做了一些研究,似乎我正在访问不存在或不应该存在的内存。我知道这是一个简单的解决方法,但我对 C++ 很陌生,所以任何事情都会受到赞赏。

vector<int> alternate(vector<int> a, vector<int> b)
{
    int n = a.size();
    int m = b.size();

    vector<int> c(n + m);

    int i;

    for(i = 0; i < a.size() and i < b.size (); i++)
    {
        c.push_back(a[i]);
        c.push_back(b[i]);
    }

    return c;
}

int main () {

    vector<int> a,b,c;
    int temp1;
    int temp2;

    while (temp1 != -1) {
        cin >> temp1;
        if(temp1 == -1) {
            break;
        }
        a.push_back(temp1);
    }

    while (temp2 != -1) {
        cin >> temp2;
        if(temp2 == -1) {
            break;
        }
        b.push_back(temp2);
    }

    c = alternate(a,b);

    int i;
    for(i = 0; i < c.size(); i++) {
        cout << c[i] << endl;
    }
}

【问题讨论】:

  • 通过使用没有值的变量,您可以立即获得未定义的行为。您应该首先解决这个问题,因为从本质上讲,未定义的行为可能会导致任何事情发生
  • 如果您可以访问一个,您应该使用调试器单步执行您的代码。即使没有,您也可以使用一堆 std::cout 语句来向您展示代码的去向以及所有内容的价值。
  • 您是否尝试过使用调试器单步执行您的程序并查看崩溃发生的位置?
  • while (&lt;variable&gt; != 1) 更改为while (true)。您已经在循环中检查-1,无需再次检查。
  • @Barmar 或更好:while (std:cin &gt;&gt; temp &amp;&amp; temp != -1).

标签: c++ memory vector


【解决方案1】:

据我所知,这里有两个问题:

  1. 您在条件中使用了temp1temp2,但您没有初始化它们,这是一个UB。试试int temp1 = 0; int temp2 = 0;
  2. 在函数alternate 中,您将使用两个输入向量之和来初始化返回向量,例如vector&lt;int&gt; c(n + m);,然后使用push_back 添加这些输入的元素。这样,您将在返回向量的开头有 n+m 零,然后是输入的元素。我很确定你不想要这个。您不需要为向量指定默认大小,只需使用push_back,或者如果您坚持使用默认大小,则为向量的索引分配值。

【讨论】:

  • 对于#1,他应该在设置之前删除使用temp1temp2 的代码。不需要该代码。
  • @Barmar 没错,这是一种无用的仔细检查,但无论如何,始终初始化变量是一种好习惯。
  • @Hamed 谢谢你的帮助!你能够指出我正确的方向,我能够解决它。
【解决方案2】:

您的代码存在一些问题,其中一些问题已在上文中提及。最重要的问题如下:

  1. temp1 和 temp2 未初始化。根据您的编译器,当在 while 循环中访问时,它们可能是 0 或某个随机数。
  2. 最终向量太大。当您创建 c 时,您正在创建它的大小为 n+m,因此它已经有那么多元素,每个元素的值都为 0。然后您将其他向量的元素相加,得到一个大致为 (n +m)*2 大小。
  3. 我在上面说“大致”是因为另一个问题是,除非 n==m,否则您的最终向量将丢失 a 和 b 中较大者的最后一个元素。您需要迭代到较大的 n 和 m,检查 while 循环以确保您可以安全地访问项目。

其他较小的问题如下:

  1. 当您将 a 和 b 传递给备用时,您正在制作它们的副本。通过使用 const 引用,您可以避免复制。
  2. 虽然不太可能,但 a 或 b 可能包含比“int”引用的更多的项目。使用 size_t 是安全的。或者甚至更好地使用“auto”来让编译器自动确定正确的类型。
  3. 通过将临时变量引入“for”和“while”循环来限制它们的可见性。
  4. 尽可能使用较新的向量 for 循环来避免对索引的需求(交替使用是不可能的,但在写出最终结果时是可能的。

毕竟,结果应该如下所示:

#include <iostream>
#include <vector>

using namespace std;

vector<int> alternate(const vector<int>& a, const vector<int>& b)
{
    const auto n = a.size();
    const auto m = b.size();
    const auto N = max(n, m);

    vector<int> c;
    c.reserve(n+m);

    for(size_t i = 0; i < N; ++i)
    {
        if (i < n) c.push_back(a[i]);
        if (i < m) c.push_back(b[i]);
    }

    return c;
}

int main () {

    vector<int> a,b,c;

    while (true) {
        int temp;
        cin >> temp;
        if(temp == -1) {
            break;
        }
        a.push_back(temp);
    }

    while (true) {
        int temp;
        cin >> temp;
        if(temp == -1) {
            break;
        }
        b.push_back(temp);
    }

    c = alternate(a,b);

    for (auto val : c) {
        cout << val << endl;
    }
}

【讨论】:

  • 非常感谢你@Stephen!我是 C++ 的初学者(我相信你可以说出来),这是我大学课程作业的问题的一部分。感谢您做出如此详细的回复,它肯定会在未来帮助我 :)
  • @Stephen 你能详细说明我是如何复制 a 和 b 的吗?
  • 当您拥有“vector a”的方法签名时,它会复制“a”并将其传递给函数。您可以通过传入“const vector& a”来避免复制,它传入对对象的常量引用而不是对象的副本。常量引用本质上是一个内部指针,因此它很便宜,但是如果您尝试更改对象,编译器会给您错误。非常量引用“vector& a”将允许函数实际更改原始对象。
【解决方案3】:

正如两个答案所指出的,未初始化的变量以及使我的“c”向量太大是罪魁祸首

【讨论】:

    猜你喜欢
    • 2017-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多