std::function 捕获中的悬空引用。为什么是未定义的行为?
Dangling references in std::function captures. Why undefined behavior?
我有几个都使用函数捕获的 C++ 程序。其中一个成功,退出代码为 0
,但另一个导致 Segmentation fault
错误。 std::shared_ptr<std::string>()
是通过引用捕获的,应该在调用 lambda 之前销毁。如果是这样,那为什么我的第一个程序成功了,而第二个程序却没有呢?
成功的计划
#include <string>
#include <memory>
#include <iostream>
#include <functional>
std::function<void()> lambda;
void assign_closure() {
std::shared_ptr<std::string> ptr = std::make_shared<std::string>("nope");
lambda = [&ptr]() {
std::cout << "Trying to print this should segault: " << *ptr << std::endl;
};
}
int main(int, char*[]) {
assign_closure();
lambda();
return 0;
}
程序失败
#include <string>
#include <memory>
#include <iostream>
#include <functional>
std::function<void()> lambda;
void assign_closure() {
std::shared_ptr<std::string> ptr = std::make_shared<std::string>("nope");
lambda = [&ptr]() {
std::cout << "Trying to print this should segault: " << *ptr << std::endl;
};
}
void do_some_work() {
std::cout << "doing some work" << std::endl;
}
int main(int, char*[]) {
assign_closure();
do_some_work();
lambda();
return 0;
}
是否有我可以用来发现悬空引用的编译器标志?
未定义的行为并不意味着段错误,它意味着任何东西。 "It works" 或 "format harddrive" 或 "segfault" 或 "email your browser history and passwords to all of your contacts"。
在这种情况下,堆栈和堆中的垃圾内存恰好被布置成non-garbage。
为防止这种情况,请勿使用任何类型的 [&]
捕获,除非 lambda 和所有副本在当前作用域结束前被丢弃。
无法确定地检测 C++ 上的所有悬挂引用。以不会为 99% 的代码产生悬空引用风险的方式编写代码。在 1% 中,无论出于何种原因,你都不能,要非常小心,大量评论,并包括没有悬空引用的证据。
有许多工具可以或多或少地帮助追踪悬空引用,但是 none 足够可靠,可以应对坚持做蠢事的程序员。在 SO 上询问工具推荐显然是题外话。
我有几个都使用函数捕获的 C++ 程序。其中一个成功,退出代码为 0
,但另一个导致 Segmentation fault
错误。 std::shared_ptr<std::string>()
是通过引用捕获的,应该在调用 lambda 之前销毁。如果是这样,那为什么我的第一个程序成功了,而第二个程序却没有呢?
成功的计划
#include <string>
#include <memory>
#include <iostream>
#include <functional>
std::function<void()> lambda;
void assign_closure() {
std::shared_ptr<std::string> ptr = std::make_shared<std::string>("nope");
lambda = [&ptr]() {
std::cout << "Trying to print this should segault: " << *ptr << std::endl;
};
}
int main(int, char*[]) {
assign_closure();
lambda();
return 0;
}
程序失败
#include <string>
#include <memory>
#include <iostream>
#include <functional>
std::function<void()> lambda;
void assign_closure() {
std::shared_ptr<std::string> ptr = std::make_shared<std::string>("nope");
lambda = [&ptr]() {
std::cout << "Trying to print this should segault: " << *ptr << std::endl;
};
}
void do_some_work() {
std::cout << "doing some work" << std::endl;
}
int main(int, char*[]) {
assign_closure();
do_some_work();
lambda();
return 0;
}
是否有我可以用来发现悬空引用的编译器标志?
未定义的行为并不意味着段错误,它意味着任何东西。 "It works" 或 "format harddrive" 或 "segfault" 或 "email your browser history and passwords to all of your contacts"。
在这种情况下,堆栈和堆中的垃圾内存恰好被布置成non-garbage。
为防止这种情况,请勿使用任何类型的 [&]
捕获,除非 lambda 和所有副本在当前作用域结束前被丢弃。
无法确定地检测 C++ 上的所有悬挂引用。以不会为 99% 的代码产生悬空引用风险的方式编写代码。在 1% 中,无论出于何种原因,你都不能,要非常小心,大量评论,并包括没有悬空引用的证据。
有许多工具可以或多或少地帮助追踪悬空引用,但是 none 足够可靠,可以应对坚持做蠢事的程序员。在 SO 上询问工具推荐显然是题外话。