如何修复D语言中的“内存泄漏”问题

3

我已经寻找了一段时间的解决方案。我编写了一个程序,从两个不同的文本文件中获取数据,对其进行解析,并输出到另一个文本文件和ARFF文件中,以供Weka分析。我遇到的问题是,我编写的用于处理数据读取和解析操作的函数没有正确释放内存。每次调用会使用额外的大约100MB内存,而我需要在该函数中调用此函数60多次。是否有方法可以强制D语言对数组、动态数组和关联数组等进行内存释放?

我的问题示例:

struct Datum {
     string Foo;
     int Bar;
} 

Datum[] Collate() {
    Datum[] data;
    int[] userDataSet;
    int[string] secondarySet;
    string[] raw = splitLines(readText(readFile)).dup;

    foreach (r; raw) {
        userDataSet ~= parse(r);
        secondarySet[r.split(",").dup] = parseSomeOtherWay(r);
    }

    data = doSomeOtherCalculation(userDataSet, secondarySet);

    return data;
}

完成文件解析后,将指针设置为null。 - Raghuveer
我并不感到惊讶。每次调用Collate()函数都会读取整个文件,并将其拆分为字符串... - DejanLekic
我看到你在返回data变量之前没有声明它。这个变量是在模块级别作用域吗?对于readFile也是一样。我只能假设这些变量在函数执行结束后仍然存在,并且是内存累积的地方。尝试通过值传递将“readFile”传递到函数中,看看是否有所不同,并尝试在函数内部声明data - Ryan
@Raghuveer 我的代码中没有隐式使用指针。我使用的动态数组相关的指针需要显式地设置为NULL吗? - Woody1193
@DejanLekic 这里有多个文件。这是我实际函数的简化版本,它会根据传递的字符串选择适当的文件。这些文件本身并不是很大,如果可以重新分配空间,存储数据所需的空间是可以接受的。 - Woody1193
@Ryan 数据在函数的第一行中声明。 - Woody1193
2个回答

4
返回结果如下:
你返回的数据中的字符串是否仍然指向原始文本文件内部?
D语言中的数组切片操作不会复制数据,而是只存储指针和长度。这也适用于splitLines、split和可能的doSomeOtherCalculation。这意味着只要原始文件文本的子字符串存在于程序中的任何位置,就无法释放整个文件的内容。
如果你返回的数据仅是所读取文本文件大小的一小部分,可以使用.dup复制字符串。这将防止小字符串固定整个文件内容在内存中。

非常感谢,它不再占用1.8GB的内存并导致崩溃,而是只使用了500MB的内存并保持稳定。我会将这个记在心里,以备将来之需。 - Woody1193

0
如果在调用Collate()后,Collate()结果的内容重复出现,很可能是因为它没有被垃圾回收器收集,因此仍然驻留在内存中,而不再使用。如果是这样的话,你可以使用一个全局容器,在每次Collate()之后将其重置:
void Collate(out Datum[] data) {
    // data content is cleared because of 'out' param storage class
    // your processing to fill data
}

谢谢您的建议。我实际上尝试过这个方法,但是数据大小观察到有时会减少,有时会增加,所以这似乎不是问题的原因,除非它是指其他的东西。 - Woody1193

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