C++ 当容器在使用前被破坏/修改时发出警告(通过引用元素或迭代器使用)
C++ warning when container destroyed/modified before its usage (usage via reference to an element or an iterator)
我将从我最近遇到的一个问题开始 - 我有一个向量,我采用了它的迭代器,我存储了迭代器(开始,结束),然后容器超出了范围,因此被破坏了。我不记得有任何编译器警告。这是一个艰难的调试,因为只有当我在非常大的数据集上运行它时,我才会出现段错误。有没有办法在使用迭代器时出现编译器错误/警告/容器修改(放大/缩小)/销毁后对容器项的任何引用?我错过了什么吗?我认为它与const
限定符同样重要,因为没有人想要引用混乱容器中的项目,对吧?
我被迫回忆起上述情况,因为现在我有另一个家庭作业 - 创建一个特定的容器。我必须返回代理引用,而不是对某个内存位置的引用,因为在分配给代理引用后,容器的一部分必须写入磁盘。但仅供参考,也许并不重要,它同样可以成为这个问题的正常参考。我想将返回代理引用(或任何返回迭代器的方法)的方法标记为"锁定">,这意味着在引用/迭代器的生命周期内的容器将有效地表现为const
。(虽然是不同的const
,允许修改单个项目,但禁止修改容器,比如宏属性,例如允许在这个"宏常量"对象上返回 operator[] 的非常量引用)
如何在 c++ 中执行此操作?这个概念在其他语言中存在吗?或者可能是为什么它不起作用? 正如我之前所说,我认为这个概念足够普遍,因为首先数据结构是任何程序的构建块,其次是因为没有人想要引用混乱容器中的项目。
有没有办法在使用迭代器时出现编译器错误/警告/容器修改(放大/缩小)/销毁后对容器项目的任何引用?
是的。它称为静态分析器。如果您使用的是 llvm,则 clang 静态分析器可以帮助您在释放内存后找到内存的一些使用情况。其他编译器也有类似的工具。它们还可以告诉您其他有用的事情,例如何时可以在不初始化的情况下使用变量,以及类似性质的事情。
我想将返回代理引用(或任何返回迭代器的方法)的方法标记为"锁定",这意味着在引用/迭代器的生命周期内,容器将有效地表现为常量。 (虽然是不同的常量,允许修改单个项目,但禁止修改容器,比如宏属性,
我不知道有什么方法可以让编译器在容器被修改时给你错误或警告。但是,可以使用信号量或互斥锁锁定对资源的访问。这将阻止其他代码在使用容器时对其进行修改。还可以编写容器修改方法,以便在资源锁定时调用它们时throw
异常。
概括一下你的问题,通常最好传递/保留指向实际容器的引用或指针,而不是迭代器,因为迭代器应该被视为短暂的——它们在许多操作中无效(例如插入和删除元素)。
要处理生存期,您可以将std::shared_ptr
传递给(或返回)对象,以确保它在程序的另一部分仍在使用时不会被释放。
关于调试,除了@user1118321提到的静态分析之外,您还可以使用地址清理器(对于 clang,编译并与-fsanitize=address
链接,在您的情况下,这将终止程序并带有错误AddressSanitizer: heap-use-after-free
和关于发生上下文的非常详细的报告。
关于你关于"锁定"的问题,受到关于使用 Rust 的评论的启发@melpomene:你可以通过将对象移动到另一个函数(从而"锁定"它)然后通过返回它来获得类似于在 rust 中借用的语义(使用std::move()
个),然后通过返回它将其移回。但是,在被调用的函数返回("返回/解锁")该对象之前,您根本无法使用该对象。
- 隐式重新解释引用时强制转换,没有警告/错误
- 警告 C4101 未引用的局部变量
- 链接时突然收到maxrregcount警告和未定义的引用错误
- 警告:返回对临时 - 奇怪情况的引用(对 Rvalue 的澄清)
- 是否有将引用返回到临时引用的C++警告?
- 为什么 ++ 运算符触发器返回对局部变量警告的引用
- C++ 当容器在使用前被破坏/修改时发出警告(通过引用元素或迭代器使用)
- 是否有任何C++编译器可以发出悬而未决的引用警告?
- 警告#13212:引用需要堆栈对齐功能的EBX
- 使用引用不会导致有关未定义行为的警告
- 三元运算符:编译器不发出局部变量警告的返回引用
- 为什么 C++ 编译器不警告返回对局部变量的引用
- 模板类型推导警告返回对本地临时对象的引用
- 为什么 g++ 警告返回对临时的引用
- 返回对函数参数的引用时没有 clang 警告
- 尝试将 std::vector<std::p air<T, U>> 转换为其左值引用时收到 VS 编译器警告 C4239
- GCC 关于隐式取消引用的警告
- 警告-未引用的内联函数已被删除
- 如何在没有编译器警告的情况下返回对空字符串的 const 引用?
- 没有返回对局部变量的引用的编译器警告