【问题标题】:Same code won't work (kind of) in a shared library, but works when used directly in the program相同的代码在共享库中不起作用(有点),但在程序中直接使用时起作用
【发布时间】:2016-05-02 05:04:51
【问题描述】:

我创建了一种脚本语言,当它运行良好时,我将所有代码放在一个共享库中,并为它制作了一个包装器,但相同的代码在共享库中不起作用。我注意到代码在共享库中运行得更快,但由于内存问题,它总是崩溃,说索引超出数组长度,但相同的代码在库外完美运行。
我还注意到,如果我减少它必须做的工作量,它会在崩溃之前持续更长时间。

我的问题是,是什么导致了这次崩溃,我该如何阻止它发生?

P.S:我没有包含所有代码,因为整个代码有 1039 行(但如果您需要代码来解决问题,那么我可以链接到它),但我已经跟踪了一个函数的崩溃.令人困惑的是,该函数总是在第 821 次被调用时崩溃,以前从未有过,这是为了更优化的代码,当代码未优化并使用更多 CPU 时,它会在 702 处崩溃。

另外:我使用的是 DMD2,函数是使用 extern(C) 导出的,我正在 Linux 系统 Ubuntu 14.04 上测试所有这些。这就是我编译库的方式:

dmd -debug -gc "qscript.d" "qcompiler.d" "lists.d" "dllmain.d"  "-shared"  "-odobj/Debug" "-of/home/nafees/Desktop/Projects/QScr/QScr/bin/Debug/libQScr.so" -w -vcolumns

并使用 dlopen 函数加载。

如果您错过了我的问题:是什么导致了这次崩溃,我该如何阻止它发生?编辑:如何禁用垃圾收集器,gc.disable 不起作用,gc 未定义。

编辑:我已经跟踪了崩溃发生的“原因”,我在所有文件中都放置了调试代码,只是为了发现垃圾收集器正在弄乱内存中加载的脚本文件。我通过添加检查来“解决”问题,而不是实际上。它检查脚本是否“正常”,将其重新加载到内存中。这是避免崩溃,但问题仍然存在。这会将问题更改为:
如何禁用垃圾收集器> 顺便说一句,我尝试了 gc.disable,但 DMD 说 gc 未定义。

【问题讨论】:

  • MVCE 需要。
  • 我已经更新了问题,现在我需要禁用垃圾收集器。

标签: crash shared-libraries d dmd


【解决方案1】:

您必须在首次加载共享库时初始化运行时。为此,您需要将类似的内容添加到您的库中:

private __gshared bool _init = false;
import core.runtime: rt_init, rt_term;

export extern(C) void init()
{
    if (!_init) rt_init;
}

export extern(C) void terminate()
{
    if (_init) rt_term;
    _init = false;
}

我的真正意思是那样,而不是完全那样。由于我们不知道您的脚本引擎是如何使用的,因此初始化计数器也可能有效:

private __gshared uint _init;
import core.runtime: rt_init, rt_term;

export extern(C) void init()
{
    if (!_init) rt_init;
    ++init;
}

export extern(C) void terminate()
{
    --init;
    if (!_init) rt_term;
}

无论如何你应该明白的。 GC 未定义,因为您没有初始化低级 D 运行时。

【讨论】:

    【解决方案2】:

    自己解决了这个问题。正如我在问题编辑中所说:我将问题跟踪到垃圾收集器,垃圾收集器弄乱了加载到内存中的脚本文件,导致库崩溃,因为垃圾收集器已从记忆。为了解决这个问题,我补充说:

    import core.memory;
    ...
    GC.disable();
    

    这解决了整个问题。

    【讨论】:

    • 禁用 GC 只是掩盖了问题。正如迈克所要求的,发布一个 MCVE,以便我们找到真正的问题。我怀疑您将 GC 分配的内存传递给 C 库,而 D 不会扫描它。
    • 我明天会发布 MVCE,时间不多了。崩溃发生在库中,主机与崩溃没有任何关联,主机只是调用一个函数(从库中),将脚本的路径传递给它。
    • 库是否保留对该路径字符串的引用?如果是,那么它可能会被收集; D GC 不知道 C 库持有的引用。
    猜你喜欢
    • 1970-01-01
    • 2015-09-03
    • 1970-01-01
    • 1970-01-01
    • 2018-11-05
    • 2021-12-07
    • 2017-02-11
    • 1970-01-01
    • 2016-12-17
    相关资源
    最近更新 更多