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" 文本 - 文本通过初始化总是存在的。
我目前正在处理一个使用不同语言设置的项目。为了解决这个问题,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" 文本 - 文本通过初始化总是存在的。