【问题标题】:C++ find_if causing crash with bind functionC++ find_if 导致绑定函数崩溃
【发布时间】:2021-10-07 10:29:36
【问题描述】:

情况有点复杂,但我会尽量解释清楚。
我正在尝试从对象指针向量中获取指向对象的指针,其中对象的属性之一与变量字符串匹配。为此,我将字符串变量绑定到一个函数,然后使用绑定函数尝试找到该对象指针。但是,每当我尝试此操作时,它都会崩溃。我已经尝试了一堆不同的测试来找到问题,但我仍然一无所知。以下是相关代码:

class A {
std::string n;
...
public:
const std::string getN() {
return n
}
};
static bool checkN(std::string n1, A* a) {
        if (a->getN() == n1) {
            return true;
        }
        else {
            return false;
        }
    }
void function() {
using namespace std::placeholders;
A* a;
std::string compare = "Yes";
const std::vector<A*> As; //As[0].n = "Yes";
auto check = std::bind(checkN, compare, _1);
a = (*std::find_if(As.begin(), As.end() - 1, check));  //This is the line where it crashes.
}

请注意,这是一个简化版本,但我认为它明白了这一点。有什么建议? 编辑:在尝试简化代码时出现了一些语法错误。修复它们。

【问题讨论】:

  • 我建议首先使用地址清理程序进行编译。但是,相关代码对我们来说几乎没有 minimal reproducible example 有用,尤其是在崩溃时,问题很容易出现在看起来无关紧要的地方。
  • 崩溃时变量的值是多少?是什么让您认为As.end() - 1 有效?甚至有用——你是否试图忽略最后一个元素?
  • 您的代码没有显示您将任何内容放入向量中...这是一个工作示例:onlinegdb.com/KziZkSl7y 主要担心的是您的代码仅在向量实际包含匹配项时才有效item - 如果不是,您取消引用结束迭代器,即 UB。以下是处理这种情况的示例:onlinegdb.com/WAPHS5Dxl

标签: c++ algorithm vector c++17 bind


【解决方案1】:

As 是一个 const std::vector&lt;A*&gt;,其中包含 no 元素,因此在这种情况下,取消引用 std::find_if(...) 返回的迭代器是未定义的行为。 p>

由于您在std::find_if(...) 中没有提及您为什么要使用As.end() - 1,因此我假设您这样做是为了摆脱分段错误,但恐怕不会摆脱上面的问题也一样。

现在,您要做来防止这种未定义的行为发生是检查std::find_if(...)返回的迭代器是否是不超过容器的最后一个元素(即检查是否std::find_if(...) != As.end(),然后才应该尝试取消引用std::find_if(...) 返回的迭代器。

#include <functional>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <iomanip>
#include <vector>
#include <string>

// ...

int main() {
    using namespace std::placeholders;

    std::string compare = "Yes";

    const std::vector<A*> As;

    // Store the iterator returned by 'std::find_if(...)' inside a variable
    auto it = std::find_if(As.begin(), As.end(), std::bind(checkN, compare, _1));

    // Check whether the iterator is NOT past the last element i.e. check if it is not equals 'As.end()'
    if (it != As.end())
        std::cout << std::quoted(compare) << " found at index " << std::distance(As.begin(), it) << "!" << std::endl;
    // Otherwise, if the iterator is, in fact, equals 'As.end()', then it is safe to assume that the element was not found
    else
        std::cout << std::quoted(compare) << " was not found." << std::endl;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-25
    • 2011-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多