“节类型冲突"由于 GCC 4.8.2 中的宏定义 [英] "Section type conflict" due to macro definition in GCC 4.8.2

查看:23
本文介绍了“节类型冲突"由于 GCC 4.8.2 中的宏定义的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我在内联函数中调用宏,我会收到节类型冲突".在 WWW 中找不到关于此错误的任何信息.

I get a "section type conflict" if I call a macro in an inlined function. There is nothing which can be found about this error in the WWW.

宏的目的是提供一个宏来处理保存在 Arduino 闪存中的字符串(只是一个侧面信息).如果函数没有内联,一切都很好.可能是什么原因?

The intention of the macro is to offer a macro to deal with strings saved in the flash for Arduino (just a side info). If the function is not inlined everything is fine. What may be the reason?

#undef PROGMEM
#define PROGMEM __attribute__(( section(".progmem.data") ))

#undef PSTR
/* need to define prog_char in avr-gcc 4.7 */
#if __AVR__ && __GNUC__ == 4 && __GNUC_MINOR__ > 6
typedef char prog_char;
#endif
/* Need const type for progmem - new for avr-gcc 4.6 */
#if __AVR__ && __GNUC__ == 4 && __GNUC_MINOR__ > 5
#define PSTR(s) (__extension__({static const prog_char __c[] PROGMEM = (s); \
                                  (const prog_char_t *)&__c[0]; }))
#else
#define PSTR(s) (__extension__({static prog_char __c[] PROGMEM = (s); \
                                  (prog_char_t *)&__c[0]; }))
#endif

代码:

inline void test() {
    hal.console->println("AP_Common tests\n");
    hal.console->println_P(PSTR("AP_Common tests\n") );
    hal.console->printf_P(PSTR("AP_Common tests\n") );
}

void setup(void)
{
  test();
}

void loop(void)
{
    // do nothing
}

错误:"println_P(PSTR("Bad var table\n"));"

Errors for: "println_P(PSTR("Bad var table\n") );"

AP_HAL/utility/BetterStream.h:53:57: note: in definition of macro 'printf_P'
 #define printf_P(fmt, ...) _printf_P((const prog_char *)fmt, ## __VA_ARGS__)
                                                         ^
output_debug.h:13:26: note: in expansion of macro 'PSTR'
   hal.console->printf_P( PSTR("{\"t\":\"s_cmp\",\"h\":%.1f}\n"),
                          ^
AP_Progmem/AP_Progmem_AVR.h:25:56: note: '__c' was declared here
 #define PSTR(s) (__extension__({static const prog_char __c[] PROGMEM = (s); \
                                                        ^
AP_HAL/utility/BetterStream.h:53:57: note: in definition of macro 'printf_P'
 #define printf_P(fmt, ...) _printf_P((const prog_char *)fmt, ## __VA_ARGS__)
                                                         ^
AP_test.ino:60:27: note: in expansion of macro 'PSTR'

在派生类中两次调用 PSTR() 会导致相同的问题.我认为这是一个编译器错误,导致未定义的行为.

Calling PSTR() in two times derived classes causes the same problem. I think it is a compiler bug, which leads to undefined behavior.

推荐答案

try: PROGMEM static const prog_char __c[].奇怪的是,我发现该属性必须在声明之前 不确定您的版本实际上是做什么的.这很可能就是问题所在.

try: PROGMEM static const prog_char __c[]. Strange is, that I found out the attribute must preceed the declaration Not sure what your version actually does. This might very well be the problem.

或者:节类型是存储值的本地内存节的属性.我想这是链接器报告的.PROGMEM 部分默认为 NOLOAD(这对本部分有意义).但是由于初始化,编译器要求section是相反的,从而导致错误.即使不是这样,我也会在这方面搜索问题.

Alternatively: The section type is an attribute to the locical memory section the values are stored. I suppose this was reported by the linker. the PROGMEM section is NOLOAD by default (which is makes sense for this section). However, due to the initialization, the compiler requires the section to be the opposite, thus resulting in the error. Even if that is not true, I would search the problem in this area.

一些补充说明:

  • 使用 stdint 类型,不要依赖内置类型的大小.
  • 小心'char'.仅用于实际字符,不依赖于它们的签名.如果您必须关心不同的类型(uint8_t 或 int8_t)会更合适.
  • `#undef' 宏不是在它们使用之前,而是在必要时之后.否则,意外的重新定义可能会在没有警告的情况下通过.这些错误很难调试!改用标题中的守卫.
  • 在微控制器中,常量正确性至关重要,因此请明智地使用它.不要不要避免const,即使这需要更多的努力(直到您获得更多经验).这不仅可以在编译时检测常见缺陷,还可以节省 RAM 和(甚至可能)闪存,因为非常量变量存储在 RAM 中,初始化值存储在闪存中.
  • 不要在自定义代码中使用 __ 前缀.这些应该保留给工具链的编译器和系统库).不过,您可以使用它作为后缀(但为什么在示例中??)
  • 避免类型转换.初学者代码中的大多数强制转换实际上是不必要的,或者是糟糕的界面设计的征兆.基本上:如果您不必为函数指定参数的类型,则不需要类型转换.(是的,有例外 - 这就是为什么我将其称为基本规则,而不是法律).
  • 一般来说:使用您可以从编译器获得的所有帮助.嵌入式调试并不是很有趣.
  • use stdint types, do not rely on the built-in types for their size.
  • Be careful with 'char'. Use only for actual characters and do not rely on their signed-ness. If you have to care about a different type (uint8_t or int8_t) would be more appropriate.
  • `#undef' macros not before their usage, but after if necessary. Otherwise, an unintended redefinition might pass without a warning. These errors can be very hard to debug! Use guards in headers instead.
  • In microcontrollers, const-correctness is vital, so use it wisely. Do not avoid const even if this takes more effort (until you get more experience). This will not only detect common flaw at compile-time, but also saves RAM and (possibly even) Flash as non-const variables are stored in RAM with initialization values in Flash.
  • Do not use __-prefixes in custon code. These should be reserved for the compiler and system libs of the toolchain). You might use this as suffix, though (but why in the example??)
  • Avoid typecasts. Most casts in beginner's code are actually unnecessary or a symptom of bad interface design. Basically: if you do not have to specify the type of an argument to a function, a typecast should not be required. (Yes, there are exeptions - that's why I call it a basic rule, not a law).
  • In general: use all help from the compiler you can get. Embedded debugging is not really fun.

这篇关于“节类型冲突"由于 GCC 4.8.2 中的宏定义的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆