std::将成员函数绑定到 nullptr 处的实例,导致看似随机的 this 指针

std::bind a member function to an instance at nullptr causing seemingly random this pointer

本文关键字:随机 指针 this 实例 绑定 函数 成员 nullptr std      更新时间:2023-10-16

我已经在gcc-4.8(通过Coliru)和Visual Studio 2013 RC上测试了以下程序:

#include <iostream>
#include <functional>
using namespace std;
struct foo {
    void bar() {
        cout << "this = " << this << endl;
    }
};
int main() {
    try {
        foo *ptr = nullptr;
        function<void ()> fun = bind(&foo::bar, *ptr);
        fun();
    } catch (const bad_function_call &e) {
        // never reached
        cout << "bad_function_call thrown: " << e.what() << endl;
    } 
    cin.get();
}

我知道我通过取消引用 nullptr 在这里导致未定义的行为,但我不明白我的代码的输出。根据我的理解,这应该会导致bad_function_call(因为根据我的猜测,这是调用这个 std::function 时应该抛出的内容),或者至少打印"this = 0"。

其实不然。输出是"this = ",后跟一些指针,在我测试的两个编译器上都不是 nullptr。但是,访问它会导致分段错误。

标准中是否有条款规定这一点?还是只是实现定义的"未定义行为"?

编辑:作为补充:以下代码在我的机器上输出"this = 0":

foo *ptr = nullptr;
ptr->bar();

发生的情况是bind存储参数的副本。参数的类型是 foo(因为你传递的是*ptr),因此会创建一个副本。当然,副本会得到一个无效的参数作为源,但这没有被使用,因此这似乎有效。因此,foo 的新实例存储在绑定对象中,这就是您看到的地址。

当你说你看到一个分段错误时,你指的是你的真实代码,而不是你在这里给出的例子,对吧?在您的真实代码中,我想 copy-ctor 似乎可以工作,但会创建一个实例,当您访问其(可能无效)成员时会导致分段错误。

"

Undefined"表示未定义。推理当你有未定义的行为时会发生什么是徒劳的,除非你的编译器记录了它的作用。