2

我对加载 C++ 生成的可执行文件有点困惑。我将一个巨大的常量字符串表放入目标可执行文件中。数据应嵌入可执行文件(无外部文件)中。

struct DataRecord
{
    unsigned char n1;
    unsigned char n2;
    std::string text;
};

static const DataRecord data[] = {
    {1, 2, "Hello"},
    {1, 3, "Hi"},
    {1, 4, "Bye"}
    .
    .
    VERY LONG LIST    
    .
    .
};

在我们运行代码编译生成代码后,可能会出现两种情况:

  1. 操作系统加载巨大的可执行文件(需要时间),然后运行程序,之后,程序就data可以使用数组了。

  2. 操作系统加载巨大的可执行文件(需要时间),然后运行程序,之后,程序必须制作表格并加载字符串文字并构造这些std::string对象(需要时间)。

很明显,第二个比第一个慢。

  • 如何知道哪一个会发生?
  • 拥有大量嵌入式数据的最佳方法是什么(权衡:速度和空间)?
  • 使用工具 objcopy 有用吗(我没有任何经验)?

我正在使用 gcc 4.7+,目标操作系统是 Windows/Linux/Android(NDK)

4

2 回答 2

4

在这种情况下,必须调用构造函数。您示例中字符串的构造函数不能“在编译时完成”。[编辑:由于std::string必须调用operator new()来分配内存(或以其他方式分配内存,尽管有时可以避免短字符串,但不太可能充分得出该决定以使编译器可以构建正确的数据“就地”结构——结束编辑]

在这种特殊情况下,您可以通过使用const char *而不是来避免构造std::string,但这假设字符串不会被修改,这当然可能是一个延伸[并且如果您需要所有字符串在使用std::string之前都是a ,而您使用大表中的所有字符串,几乎没有(如果有的话)好处]。

顺便说一句,(在大多数操作系统中)程序不会“一次性加载所有代码,需要很长时间”。相反,它加载“入口点”(在一个 4KB 的块中,即包含入口点的 4KB 对齐的代码块)。其他一切都是“按需加载”的——也就是说,它是根据需要加载的。

于 2013-05-15T19:40:19.670 回答
1

普通旧数据(POD)可以在编译和链接时准备好并存储在可执行文件中,因此只需将其加载到内存中即可使用。但是,具有构造函数的类的任何成员数据都可能需要调用构造函数。

我使用 Apple clang 4.0 for x86_64 编译了代码,检查了生成的代码,并逐步执行了一些代码。它确实调用了字符串构造函数并且确实调用了malloc.

理论上,激进的 C++ 实现可以将大部分工作转移到编译和链接时间,但您通常应该期望这样的数据会导致在程序启动时调用构造函数和内存分配。

于 2013-05-15T19:46:56.023 回答