我即将围绕 OpenGL 纹理实现一个托管包装类,并且我希望对象终结器调用glDeleteTextures.
因此,调用终结器的线程(GC线程?)必须通过调用绑定到纹理所属的OpenGL渲染上下文wglMakeCurrent。
但wglMakeCurrent文档明确指出,一个OpenGL渲染上下文不能同时是多个线程的当前渲染上下文。
如果GC可以随时触发,我不能保证发生时没有其他线程正在使用上下文。
glDeleteTextures调用 .net 对象的终结器的正确方法是什么?
编辑
该包装类将用于“按需加载”场景图的复杂系统,并通过WeakReference等等实现缓存策略。因此,“手动处置”不是我想要考虑的选项:我真的希望 GC 能够处理这个问题。
我在玩 ruby 终结器并注意到一些对我来说很奇怪的行为。我可以将触发代码减少到以下内容:
require "weakref"
class Foo
def initialize
ObjectSpace.define_finalizer(self, self.class.finalize)
end
def self.finalize
proc {
puts "finalizing"
}
end
end
Foo.new # does not work
#WeakRef.new(foo) # Using this instead, everything works as expected
sleep 1
ObjectSpace.garbage_collect
puts "... this did not finalize the object"
Foo.new
ObjectSpace.garbage_collect
puts "but this did?"
Run Code Online (Sandbox Code Playgroud)
正如程序所说,在第二次调用 Foo.new 之前没有运行终结器。我尝试在第一次调用垃圾收集器之前添加更多延迟(尽管据我所知,它根本不需要),但这没有任何作用。
奇怪的是,如果我使用注释掉的行 i,第一个终结器会像我期望的那样被调用。第二个在程序退出之前仍然没有被调用。
谁能解释为什么会这样?我正在运行带有 ruby 1.9.3p194(2012-04-20 修订版 35410)[x86_64-linux] 的 Ubuntu 12.10。我尝试阅读弱引用代码,但据我所知,它所做的只是存储对象 object_id 以便稍后检索它。
编辑:我知道在这种情况下手动调用垃圾收集器是没有意义的。我只是想了解这背后的机制。
我有一个已宣布的任务:
tasks.getByName('connectedAndroidTest').finalizedBy 'archiveReports'
Run Code Online (Sandbox Code Playgroud)
但是当我尝试构建项目时,它告诉我:
Caused by: org.gradle.api.UnknownTaskException: Task with name 'connectedAndroidTest' not found in project ':TestProject'.
at org.gradle.api.internal.tasks.DefaultTaskCollection.createNotFoundException(DefaultTaskCollection.java:80)
at org.gradle.api.internal.DefaultNamedDomainObjectCollection.getByName(DefaultNamedDomainObjectCollection.java:229)
at org.gradle.api.internal.tasks.DefaultTaskCollection.getByName(DefaultTaskCollection.java:31)
at org.gradle.api.tasks.TaskCollection$getByName.call(Unknown Source)
at build_6w8zk6ic8wtqwlvwwubix2jc3.run(/path/to/build.gradle:84)
at org.gradle.groovy.scripts.internal.DefaultScriptRunnerFactory$ScriptRunnerImpl.run(DefaultScriptRunnerFactory.java:91)
... 58 more
Run Code Online (Sandbox Code Playgroud)
如果我将其更改为其他方式:
tasks.connectedAndroidTest.finalizedBy 'archiveReports'
Run Code Online (Sandbox Code Playgroud)
这个问题非常相似:
Caused by: groovy.lang.MissingPropertyException: Could not get unknown property 'connectedAndroidTest' for task set.
at org.gradle.internal.metaobject.AbstractDynamicObject.getMissingProperty(AbstractDynamicObject.java:92)
at org.gradle.internal.metaobject.AbstractDynamicObject.getProperty(AbstractDynamicObject.java:62)
at org.gradle.api.internal.tasks.DefaultTaskContainer_Decorated.getProperty(Unknown Source)
at build_6w8zk6ic8wtqwlvwwubix2jc3.run(/path/to/build.gradle:84)
at org.gradle.groovy.scripts.internal.DefaultScriptRunnerFactory$ScriptRunnerImpl.run(DefaultScriptRunnerFactory.java:91)
... 58 more
Run Code Online (Sandbox Code Playgroud)
我知道这个任务是由于风格而动态生成的,但是如何向动态任务添加终结器?
finalizer gradle build.gradle android-gradle-plugin gradle-task
我阅读了类似问题的已接受答案,部分答案是:
当结构作为参数传递时,它们是按值传递的:它们被复制。现在你有两个具有相同内部字段的结构,它们都将尝试清理同一个对象。一个会首先发生,因此随后使用另一个的代码将开始神秘地失败......然后它自己的清理将失败
同样的问题不也适用于吗Dispose()?如果结构可以实现IDisposable,那么不允许它们具有终结器的原因是什么?
如果终结器的全部目的是Dispose(false)在程序员忘记调用时进行调用Dispose(),并且结构可以具有IDisposable.Dispose(),那么为什么不允许结构的终结器而允许它们用于引用类型呢?
我有一个TestNet本机组件的包装器。本机组件公开了一个通过调用托管回调与托管部分进行通信的阻塞 ,以及一个用于检索对 .NET 包装器的引用并提供上下文的弱函数。它很弱,因为 .NET 包装器旨在隐藏正在向用户处理非托管资源的事实,并且故意不实现该接口:非弱它会根本阻止实例被收集,从而造成内存泄漏。发生的情况是,在发布版本中,只有垃圾收集器会在执行托管回调时收集对 .NET 包装器的引用,甚至在两者之前并且令人惊讶地解除阻塞。我自己理解这个问题,我可以通过在 P/Invoke 调用后发出 a 来解决它,但由于这方面的知识不是很广泛,似乎很多人都做错了。我有几个问题:TestNative::Foo()GCHandleGCHandleIDisposableTestNetTestNative::Foo()TestNet::Foo()GC.KeepAlive(this)
GC.KeepAlive(this)最后一条指令是对非托管资源的 P/Invoke 调用,或者仅在这种特殊情况下需要,即在从本机代码封送托管回调时切换到托管执行上下文,则托管方法中始终需要该指令?问题可能是:我应该GC.KeepAlive(this)到处放吗?这个旧的微软博客(原始链接是404,这里被缓存)似乎是这么建议的!但这将改变游戏规则,基本上这意味着大多数人从未正确执行过 P/Invoke,因为这需要在包装器中检查大多数 P/Invoke 调用。例如,是否有一条规则规定,当执行上下文非托管(本机)时,垃圾收集器(编辑:或更好的终结器)无法为属于当前线程的对象运行?GC.KeepAlive(this) 策略。一般来说,在处理终结器GC.KeepAlive(this)时似乎很少需要。注意:我对收集代表没有问题,这是一个不同的问题,我知道如何正确处理。这里的问题是,当 P/Invoke 调用尚未完成时,会收集持有非托管资源的对象。
它遵循的代码清楚地表明了问题。创建一个 C# 控制台应用程序和一个 C++ Dll1项目并在发布模式下构建它们:
程序.cs:
using System;
using System.Runtime.InteropServices;
namespace ConsoleApp1
{
class Program
{
static void …Run Code Online (Sandbox Code Playgroud) 当我关闭互联网连接并从 Firebase 应用注销时,我无法退回我的应用。
还得到下一个错误:
2019-11-05 20:26:19.364 5593-5611/com.mandarine.target_list E/System:
Uncaught exception thrown by finalizer 2019-11-05 20:26:19.3655593-5611/com.mandarine.target_list E/System:
java.lang.NullPointerException: Null reference used for synchronization (monitor-enter)
at com.android.org.conscrypt.ConscryptFileDescriptorSocket.finalize(ConscryptFileDescriptorSocket.java:1053)
at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:252)
at java.lang.Daemons$FinalizerDaemon.runInternal(Daemons.java:239)
at java.lang.Daemons$Daemon.run(Daemons.java:105)
at java.lang.Thread.run(Thread.java:764)
Run Code Online (Sandbox Code Playgroud)
它仅在我关闭 Internet 时发生。
我也发现了这个:https : //github.com/google/conscrypt/blob/master/common/src/main/java/org/conscrypt/ConscryptFileDescriptorSocket.java#L1079
但真的不知道该怎么做必须得到
我也做了/gradlew app:androidDependencies并得到:
> releaseUnitTestRuntimeClasspath - Dependencies for runtime/packaging
> +--- org.jetbrains.kotlin:kotlin-android-extensions-runtime:1.3.50@jar
> +--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.50@jar
> +--- com.firebaseui:firebase-ui-auth:4.3.1@aar
> +--- androidx.navigation:navigation-ui-ktx:2.0.0@aar
> +--- androidx.navigation:navigation-ui:2.0.0@aar
> +--- com.google.android.material:material:1.0.0@aar
> +--- me.zhanghai.android.materialprogressbar:library:1.4.2@aar
> +--- androidx.appcompat:appcompat:1.0.2@aar
> +--- androidx.constraintlayout:constraintlayout:1.1.3@aar
> +--- …Run Code Online (Sandbox Code Playgroud) android garbage-collection finalizer nullpointerexception kotlin
考虑下面的小程序,它重现了我在 mac os 上使用 gfortran gcc 9.2.0 时遇到的分段错误):
module stringmod
type :: str_t
character(len=:), allocatable :: s
contains
final :: finalize
end type str_t
type :: static_t
type(str_t) :: expr(3)
end type static_t
type :: dynamic_t
type(str_t), allocatable :: expr(:)
end type dynamic_t
contains
subroutine finalize ( x )
type(str_t), intent(in out) :: x
if (allocated(x%s)) deallocate(x%s)
end subroutine finalize
end module stringmod
use stringmod
implicit none
type(static_t ), allocatable :: stat(:)
type(dynamic_t), allocatable :: dyna(:)
integer :: i, j, …Run Code Online (Sandbox Code Playgroud) 我在我的类中实现了Finalize和Dispose,我在我的父类上实现了IDisposable并覆盖了我的子类中的Dispose(bool)重载.我不确定
这两件事都是在这里给出的例子中完成的 -
虽然此MSDN文章中的示例没有这两个中的任何一个 - http://msdn.microsoft.com/en-us/library/b1yfkh5e.aspx
而MSDN中的这个例子并不完整 - http://msdn.microsoft.com/en-us/library/ms182330.aspx
我有一个终结器似乎总是在应用程序关闭期间失败.我认为这是因为它持有一些在那时不再有效的本地资源.有没有办法在析构函数/终结器中告诉它是否因应用程序关闭而被调用?
谢谢!
所以我很好奇,GC会 - 尤其是最终化 - 会x在.NET中的实例上发生:
x 什么都没有引用x有一个静态DbConnection属性y 是与...相同的类的实例 xy 仍被某事引用令我感到震惊的是,在这种情况下,x可以通过外部引用声明死亡 - 但是对它执行最终化可能会导致DbConnection在y仍然需要时进行处理并保留对它的引用.
那么,在我描述的场景中,它被x收集了吗?它最终确定了吗?或者,在收集其中任何一个实例之前,所有类型的实例都需要在堆中进行孤立吗?每个实例都会发生最终化吗?
我会这么认为,遵循的一般规则是:永远不要触摸终结器中的静态或其他共享对象?
finalizer ×10
c# ×5
.net ×4
destructor ×2
idisposable ×2
android ×1
build.gradle ×1
callback ×1
fortran ×1
gfortran ×1
gradle ×1
gradle-task ×1
kotlin ×1
opengl ×1
pinvoke ×1
ruby ×1
wpf ×1