Error[Lp001] 运行 内存不足而我不应该

Error[Lp001] running out of memory when I shouldn't

我目前正在处理一个使用不同语言设置的项目。为了解决这个问题,table 用于存储程序中使用的不同语言的所有文本。因此,每当要在屏幕上写入文本时,都会调用此 table 并根据当前语言设置返回文本字符串。我最近加入了这个项目,我注意到存储它的方式不是很优化,并且对于添加的每一种新语言,查找正确字符串所需的时间都会增加。因此,我想出了一个(在我看来)更好的解决方案。然而,当我尝试实现它时,我 运行 遇到了一个错误,即使用了太多内存,我不明白为什么。我正在使用嵌入的 IAR workbench.

pseudo/c++代码中的原解:

typedef struct
{
    enum textId;
    enum language;
    string textString;
} Text;

static const Text s_TextMap[] = 
{
     { TextId::RESTORE_DATA_Q                ,Language::ENGLISH        ,"Restore Data?"                          },
     { TextId::RESTORE_DATA_Q                ,Language::SWEDISH        ,"Återställa data?"                       },
     { TextId::RESTORE_DATA_Q                ,Language::GERMAN         ,"Wiederherstellen von Daten?"            },
     { TextId::CHANGE_LANGUAGE               ,Language::ENGLISH        ,"Change Language"                        },
     { TextId::CHANGE_LANGUAGE               ,Language::SWEDISH        ,"Välj språk"                             },
     { TextId::CHANGE_LANGUAGE               ,Language::GERMAN         ,"Sprache wählen"                         },
};

我在 pseudo/c++ 代码中的解决方案:

typedef struct
{
    const char* pEngText;
    const char* pSweText;
    const char* pGerText;
} Texts;

static Texts addTexts(const char* pEngText, const char* pSweText, const char* pGerText)
{
    Texts t;
    t.pEngText = pEngText;
    t.pSweText = pSweText;
    t.pGerText = pGerText;
    return t;
}

typedef struct
{
    enum textId;
    Texts texts;
} Text;

static const TextTest s_TextMapTest[] =
{
     {TextId::RESTORE_DATA_Q,        addTexts("Restore Data?","Återställa data?","Wiederherstellen von Daten?")},
     {TextId::CHANGE_LANGUAGE,        addTexts("Change Language","Välj språk","Sprache wählen")},
};

在一般情况下,我的解决方案的查找速度显然更快,而且根据我的计算,它还应该使用更少的内存。当使用完整的 tables 时,我计算出原始解决方案需要 7668 字节,而我的解决方案需要 4248 字节。我这样做的方法是在一个小测试程序中实现完整的 tables 并使用 sizeof(s_TextMap)。但是,当我尝试编译代码时出现链接错误:

Error[Lp011]: section placement failed unable to allocate space for sections/blocks with a total estimated minimum size of 0x130301 bytes (max align 0x1000) in <[0x0000a000-0x0007ffff]> (total uncommitted space 0x757eb).

Error[Lp011]: section placement failed unable to allocate space for sections/blocks with a total estimated minimum size of 0x47de4 bytes (max align 0x20) in <[0x1fff0000-0x2000fff0]> (total uncommitted space 0x1fff1).

Error[Lp021]: the destination for compressed initializer batch "USER_DEFAULT_MEMORY-1" is placed at an address that is dependent on the size of the batch, which is not allowed when using lz77 compression. Consider using "initialize by copy with packing = zeros" (or none) instead.

Error[Lp021]: the destination for compressed initializer batch "USER_DEFAULT_MEMORY-1" is placed at an address that is dependent on the size of the batch, which is not allowed when using lz77 compression. Consider using "initialize by copy with packing = zeros" (or none) instead.

我最困惑的错误是第一个错误,它指出我的代码估计占用 0x130301 字节的内存,我认为这是不可能的。这可能是 IAR 中的一些错误还是我遗漏了什么?

好的,所以我设法让它工作了。我删除了额外的结构和函数并将其简化为:

typedef struct
{
    TextId::e textId;
    const char* pEngText;
    const char* pSweText;
    const char* pGerText;
    const char* pFinText;
} Text;

它对我来说不太好,但至少它有效

在您的解决方案中,s_TextMapTest[] 必须位于 RAM 而不是 ROM 中,因为指针是在 运行 时间设置的 - 虽然不清楚您是如何设法使用函数调用的一个数组元素初始化器。在大多数微控制器上,RAM 是一种非常有限的资源。您没有提供有关目标或其内存映射的信息。

无论哪种方式,您都应该检查链接器的内存映射输出,以验证数据是否位于适当的位置以及您期望的位置。

您在自己的答案中提出的原始代码和解决方案是 ROMable。

在保持 ROMable 的同时保持原始提案形式的解决方案是将 addTexts() 编写为宏而不是函数:

#define addTexts( eng, swe, ger, fin ) {eng, swe, ger, fin}

虽然我看不出有什么好处,而且你并不是真正的 "adding" 文本 - 文本通过初始化总是存在的。