"新的“;以及“;删除“;在函数中

"New" and "delete" in a function

本文关键字:函数 删除 以及 新的 quot      更新时间:2023-10-16

编写用于文件操作的dll时,遇到了一些问题。

要通过file.read从文件中读取字节,我需要一个所需长度的char*数组。由于长度是可变的,我不能使用

char* ret_chars[next_bytes];

它给出了next_bytes不是常量的错误。

StackOverflow中的另一个主题说要使用:

char* ret_chars = new char[next_bytes];

不过,据我所知,用"new"创建它需要稍后使用"delete"。

现在,如果这个函数的返回值应该是这个数组,我应该如何删除这个数组?如果我不在任何地方使用"删除",这不是内存泄漏吗?

如果这有帮助的话:这是一个DLL,我将从"游戏制造者"调用。因此,我以后不可能删除任何内容。

希望有人能帮助我!

当您编写将由现有代码调用的回调时,您必须遵循其规则。

假设《游戏制造者》的作者不是十足的白痴,他们会释放你返回的记忆。因此,您必须检查文档,找出它们将使用什么函数来释放内存,然后您必须调用匹配的分配器。

在这些情况下,框架通常会提供一个专门为您设计的分配函数,用于分配返回缓冲区。

另一种常见的方法是从不返回回调分配的缓冲区。相反,框架会将一个缓冲区传递给回调,您只需填写即可。请查看文档以了解这种可能性。

是否没有编写"Game Maker"插件/扩展的示例代码?


看起来开发人员确实是十足的白痴,至少在插件接口设计方面是这样,但他们确实提供了一些指导。

请注意,您必须小心内存管理。这就是我将结果字符串声明为global的原因。

这意味着Game Maker引擎不会尝试释放返回的缓冲区。

您也可以使用全局变量,或者任何具有静态存储持续时间的变量,例如函数本地静态变量。std::vector<char>是一个不错的选择,因为它很容易调整大小。这样,每次调用函数时,为上一次调用分配的内存都会被重用或释放。因此,您的"泄漏"将限于您一次返回的金额。

char* somefunc( void )
{
    static std::vector<char> ret_buffer;
    ret_buffer.resize(next_bytes);
    // fill it in, blah blah
    return &ret_buffer[0];
}
// std::string and return ret_string.c_str(); is another reasonable option

Game Maker Language中的脚本将负责在再次调用您的函数并覆盖它之前制作该结果字符串的副本。

new char[ n ]技巧适用于运行时值,是的-您需要在使用完数组后删除[],否则数组会泄漏。

如果你无法改变"Game Maker"(无论是什么)的工作方式,那么内存就会泄露。

如果你可以更改"Game Maker"来做正确的事情,那么必须管理返回数组的生存期。

这才是真正的问题-DLL代码不知道什么时候不再需要它,所以调用的代码需要在完成时删除它,但调用代码不能直接删除它-它必须回调DLL才能删除它,因为最初是DLL的内存管理器分配的。

由于您说返回值必须是char[],因此您需要从DLL中导出第二个函数,该函数接受char[],并对其调用delete[]。然后,调用代码可以在完成之前返回的数组后调用该函数。

使用vector <char *>(或vector <char>,取决于您真正想要的——问题还不完全清楚),这样,您就不需要删除任何内容。

如果不调用delete,就不能在函数中使用new,否则您的应用程序将泄漏内存(这是一件坏事,因为即使是这样,您也将没有剩余的内存)。没有一个简单的解决方案,在某种程度上没有一些相对严格的限制。

您引用的第一个代码示例在堆栈上分配内存。您引用的第二个代码示例在堆上分配内存。(两个完全不同的概念)。

如果返回数组,那么分配内存的函数不会释放它。由调用方删除内存。如果调用者忘记了,那么是的,这是内存泄漏。

首先,如果使用new char[];,则不能使用delete,但必须使用delete []

但正如您所说,如果您在这个函数中使用new [],而最后不使用delete [],那么您的程序就会泄漏。

如果您想要一种垃圾收集,现在可以在标准c++库中使用*smart-ptr*。我认为"shared_ptr"会很好地实现你想要的。>**共享ptr**:管理指针的存储,提供有限的垃圾收集功能,可能与其他对象共享该管理。以下是有关它的一些文档:http://www.cplusplus.com/reference/memory/shared_ptr/

好的,我也会加入。

如果Game Maker没有明确表示将删除此内存,那么您应该检查它想要的缓冲区有多大,然后传入该大小的静态缓冲区。这避免了与内存管理的跨dll版本控制问题相关的各种麻烦。在他们的代码或API中必须有一些关于这一点的文档,我强烈建议你找到并阅读它。Game Maker是一个非常大且众所周知的API,所以如果你自己没有文档,谷歌应该为你提供信息。

如果您返回的是一个char指针,它看起来就像您返回的一样,那么您可以简单地对该指针调用delete。

示例:

char * getString()
{
    char* ret_chars = new char[next_bytes];
    strcpy(ret_chars, "Hello world")
    return ret_chars
}
void displayChars()
{
    char* chars = getString()
    cout << chars
    delete [] chars
}

只要确保解除分配(删除)所有分配的(新的)指针,否则就会出现内存泄漏,因为内存是分配的,然后在运行后没有收集,变得不可用。这是一种快速而肮脏的浏览方式,可以查看您是否已经释放了所有分配的空间来计算新空间和删除空间,它们应该是1比1,除非有些空间出现在条件块或循环块中。