加载时嵌入在.exe和内存管理中的二进制资源

时间:2013-12-29 13:11:48

标签: c arrays memory-management

我在一个小型C程序中工作,我需要将二进制数据嵌入到exe文件中。我使用的方法是将二进制数据转换为char []数组......但我并不直接将该数组作为全局变量包含在内;相反,我将该数组复制到一个函数(LoadResource)中,该函数在堆上动态创建一个数组,在那里我复制我的原始数据。这就是我的意思:

char *dataPntr;

void LoadResource()
{
    char data[2048] = {/*my binary data */};

    dataPntr = malloc(2048);

    for (int i = 0; i < 2048; i++) dataPntr [i] = data[i];
}

这样,如果我的理解是正确的,那么当调用LoadResource()时,data []将被放入堆栈中,复制到堆中,最后data []将自动从堆栈中释放出来;堆拷贝应该用free()手动释放。

我这样做是因为资源只在某些情况下使用,而不是总是...而且我更愿意避免使用大的全局变量。

我的问题:

运行程序时,data []数组是否放在内存中?文本片段可能吗?或者它只是在调用LoadResource()时加载到堆栈中?

我的解决方案是正确的(在内存管理方面)还是仅仅声明一个全局数据数组会更好?

感谢您的回答!

2 个答案:

答案 0 :(得分:1)

通常,避免全局变量是个好主意。我不会说你从不需要它们,但它们可能很难调试。问题是很难跟踪谁最后改变它。如果你曾经做过任何多线程,那么你再也不希望看到全局了!

我在这些评论中加入了char *dataPntr - 为什么全球化?最好还是返回指针。

不确定为什么要在堆栈上使用数组(data),我的猜测是你可以使用{...}初始化语法。你能避免吗?这可能不是什么大问题,2k不是很大的开销,但也许它可能会增长?

我个人会使用memcpy()

复制数据

你的代码,2048年和2018年有几个“神奇的数字”。也许一个是拼写错误?为避免此类问题,大多数人将使用预处理器宏。例如:

#include <string.h>      /* for memcpy() */

#define DATA_SIZE 2048

char * LoadResource(void)
{
    char data[DATA_SIZE] = {/*my binary data */};

    char * dataPntr = malloc(DATA_SIZE);

    if (dataPntr) 
        memcpy(dataPntr, data, DATA_SIZE);

    return dataPntr;
}

顺便提一下,请注意LoadResource的原型为void。在C(不是C ++)中,空参数列表表示没有参数检查,而不是没有参数。另请注意,我会检查malloc的返回值。这意味着该函数将在出错时返回NULL

另一种策略可能是改为使用data数组static,但是当初始化初始化时,编译器依赖于此,并且您可能会发现即使您不使用也会导致内存开销它

答案 1 :(得分:0)

虽然我一般同意@cdarke,但听起来你正在创建一个常量数组(即从未在运行时修改过)。如果这是真的,我会毫不犹豫地使它成为全局const数组。大多数编译器只是在链接时将数组放在文本内存中,并且初始化不会有任何运行时开销。

另一方面,如果您需要在运行时修改数据,我会按照@ cdarke的示例进行操作,但要生成data数组static const。这样,大多数编译器也会将预初始化的数组放在文本段中,您将避免初始化data数组的运行时开销。