【问题标题】:SIGILL on ideone but runs with warning on CodeblocksIDEONE 上的 SIGILL,但在代码块上运行时出现警告
【发布时间】:2015-07-21 14:32:19
【问题描述】:

我在 SPOJ 上解决了一个名为 FASHION 的简单问题……很简单。我只是想了解迭代器。但后来我遇到了一个特殊的问题。

这是我的代码,

#include <iostream>
#include <vector>
#include <algorithm>
#include <stdio.h>

using namespace std;

int hotMax(vector<int> &, vector<int> &);

int main()
{
    int iter,m_f;
    scanf("%d", &iter);

    vector<int> a,b;
    while(iter--){
        scanf("%d", &m_f);
        a.resize(m_f);
        b.resize(m_f);
        vector<int>::iterator it;
        for(it = a.begin(); it != a.end(); it++){
            scanf("%d", it);
        }
        for(it = b.begin(); it != b.end(); it++){
            scanf("%d", it);
        }
        printf("%d\n", hotMax(a,b));
    }
    return 0;
}

int hotMax(vector<int> &a, vector<int> &b){
    std::sort(a.begin(), a.end());
    std::sort(b.begin(), b.end());
    int result = 0;
    vector<int>::iterator it1,it2;
    for(it1 = a.begin(),it2 = b.begin(); it1 != a.end(); it1++,it2++){
        result+= (*it1) * (*it2);
    }
    return result;
}

我在代码块上收到此警告,

/home/harshal/c++ 教程/SAMER08F/main.cpp|22|警告:格式“%d”需要“int*”类型的参数,但参数 2 的类型为“std::vector::iterator {aka __gnu_cxx:: __normal_iterator >} /home/harshal/c++ 教程/SAMER08F/main.cpp|25|警告:格式“%d”需要“int*”类型的参数,但参数 2 的类型为“std::vector::iterator {aka __gnu_cxx:: __normal_iterator >}' [-Wformat=]|

这些对应于 scanf("%d", it); 但随后它在代码块中完美运行,

它在 ideone 和 SPOJ 上都给出了 SIGILL。

当我将 scanf 替换为 cin&gt;&gt; *it 时,它可以在 SPOJ 和 ideone 上完美运行。

如果您能给我一些见解,我将不胜感激。我试图将 it 放在 scanf 中,因为它是一种指向向量的通用指针。

提前致谢。

【问题讨论】:

    标签: c++ c++11 vector stl runtime-error


    【解决方案1】:

    scanfprintf 是遗留的 C 函数,它们不应与迭代器等 C++ 功能结合使用。具体来说,std::vector&lt;T&gt;::iterator 是实现定义的,可能不仅仅是T*,因此您不能依赖对scanf 的调用是可移植的。

    【讨论】:

    • 谢谢,但你能告诉我 SIGILL 的原因吗?
    • 可能编译器会为 scanf 调用生成一些系统调用,当它遇到实现定义为迭代器的任何内容时,它会到处喷涌。不过很难说。
    • 您是否能够重现相同的错误?这不好。我知道迭代器不仅仅是T*,而是cin&gt;&gt;*it 工作。
    • Clang 为我生成了一个ud2 指令。
    【解决方案2】:

    迭代器不一定是指针。因此,这段代码会产生未定义的行为:

    scanf("%d", it);

    您必须为scanf 提供int 变量的真实地址。如果您的实现碰巧将std::vector&lt;int&gt;::iterator 视为指针,那么您将看不到任何问题。

    这个问题有一个真实的例子:

    在 Visual Studio 6.0 流行的时候,很多使用 std::vector 的代码都假设向量迭代器是作为指针实现的,程序员是对的。当时的向量迭代器是用指针实现的。

    然后是 VS 6.0 之后的 Visual Studio。向量迭代器不再作为简单的指针实现,因此许多遗留代码要么无法编译,要么在偶然编译时被破坏。当您在编写程序时依赖实现细节时,就会发生这种情况。

    【讨论】:

    • 感谢您的解释
    猜你喜欢
    • 1970-01-01
    • 2022-11-09
    • 1970-01-01
    • 1970-01-01
    • 2020-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多