函数中的“新”和“删除”

时间:2013-07-16 16:07:17

标签: c++ dll new-operator delete-operator

为文件操作编写一个dll,我遇到了一些问题。

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

char* ret_chars[next_bytes];

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

StackOverflow中的另一个主题是使用:

char* ret_chars = new char[next_bytes];

使用“new”创建它需要稍后使用“删除”,据我所知。

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

如果这有帮助:这是我将从“Game Maker”调用的DLL。因此我之后无法删除任何内容。

希望有人可以帮助我!

7 个答案:

答案 0 :(得分:4)

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

假设“游戏制作者”的作者不是完整的白痴,他们将释放你返回的记忆。因此,您必须检查文档以找出它们将用于释放内存的函数,然后您必须调用匹配的分配器。

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

另一种常见方法是永远不会返回回调分配的缓冲区。相反,框架将一个缓冲区传递给你的回调函数,你只需填写它。检查文档中是否有这种可能性。

是否没有用于编写“Game Maker”插件/扩展程序的示例代码?


看起来开发人员确实是完全白痴,至少在设计插件界面时,他们确实提供了some guidance

  

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

这意味着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语言中的脚本将负责在再次调用您的函数之前复制该结果字符串并覆盖它。

答案 1 :(得分:1)

new char[ n ]技巧与运行时值一起使用,是的 - 当你完成数组或它泄漏时你需要删除[]数组。

如果您无法改变“Game Maker”(无论是什么)的工作方式,那么内存将会泄露。

如果您可以更改“Game Maker”来做正确的事情,那么 it 必须管理返回数组的生命周期。

这是真正的问题 - DLL代码无法知道何时不再需要它,因此调用代码需要在完成后删除它,但调用代码无法直接删除它 - 它必须回调DLL来删除它,因为它是DLL的内存管理器首先分配它。

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

答案 2 :(得分:1)

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

你不能在函数内使用new而不调用delete,或者你的应用程序会泄漏内存(这是一件坏事,因为EVENTUALLY,你将没有内存)。没有EASY解决方案,没有某种相对严格的限制。

答案 3 :(得分:0)

首先,如果您使用new char[];,则无法使用delete,但必须使用delete []

但就像你说的那样,如果你在这个函数中使用new []而不使用delete [],那么你的程序将会泄漏。

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

答案 4 :(得分:0)

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

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

答案 5 :(得分:0)

如果你要返回一个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
}

确保释放(删除)所有已分配(new'd)指针,否则您将在内存泄漏的情况下分配内存,然后在运行时之后不会收集并变得无法使用。快速而肮脏的方式浏览并查看您是否已取消分配所有已分配的空间来计算新的并计算您的删除,并且它们应该是1比1,除非某些条件出现在条件或循环块中。

答案 6 :(得分:0)

好的,我也会跳进去。

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