使用new关键字创建对象时发生罕见的分段错误

3
在Java应用程序中,我使用JNI调用几个C++方法。其中一个方法创建了一个对象,在方法完成后必须保持持久性,并在其他方法调用中使用。为此,我创建了该对象的指针,并将其作为引用返回给Java以供以后访问(注意:Java类实现了“Closable”,在“close”方法中,我调用一个方法来删除该对象)。
然而,在罕见情况下,大约经过50,000次调用后,C++代码抛出分段错误。根据日志文件的内容,只有几行代码可疑是错误的来源(它们位于上一个打印的日志消息和下一个消息之间)。
MyObject* handle = new MyObject(some_vector, shared_ptr1, shared_ptr2);
handles.insert(handle); // handles is a std::set
jlong handleId = (jlong) handle;

除了我使用旧式 C 指针之外,我想知道这里是否还有可能存在问题。多线程会是一个问题吗?或者当转换为 jlong 时,指针 ID 可能会被截断吗?

我还想指出,从我的以往经验来看,日志只是指示分段错误发生位置的粗略指标。它实际上可能发生在代码的后面,而下一条日志消息只是还未被打印。然而,复现此错误可能需要 1-2 天,因此我想检查一下这些行是否存在问题。


2
jlong 是 64 位,因此指针截断不是问题。您提到了多线程 - handles 是否受到足够的竞态条件保护? - Botje
2
你展示的代码可能是问题显现的地方。但它本身并不是问题。首先,将问题隔离成一个 [mcve] 并包含错误的回溯信息。 - Ulrich Eckhardt
@Botje @m88 谢谢,这是一个很好的观点。handles没有受到保护。我会尝试移除该设置并检查错误是否仍然存在。 - Green绿色
2
在撰写此问题时,我没有堆栈跟踪。代码正在容器中运行,除了日志外,所有内容都丢失了。昨晚我很幸运,可以在相当短的时间内复现此错误。尽管错误发生在不同的位置“handles.erase”,但我现在非常有信心,在多线程场景中使用std::set是该问题的根源。我现在正在运行更多测试,没有使用集合,并检查应用程序是否长时间稳定。 - Green绿色
1
使用任何可变容器而不进行同步会容易出现竞态条件。 - Botje
显示剩余2条评论
1个回答

0

在我的代码中移除了 std::set 后,错误不再发生。结论:多线程中的 std::set 必须受保护,以避免不可恢复的崩溃。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接