c++全局对象方法未链接
c++ global object methods not linked
我在STM32 ARM micro的C++项目中遇到问题。我创建了一个实现状态机的类。这个类有一些方法不是由其他方法直接调用的,而是由函数指针调用的:
// Foo.h
class Foo
{
public:
typedef void(Foo::*State)(void);
State state;
void init();
virtual void poll();
void state1();
void state2();
Foo();
virtual ~Foo() {}
};
// Foo.cpp
#include "Foo.h"
#define ASSIGN_STATE(X,Y)
X = &Foo::state ## Y;
void Foo::init()
{
ASSIGN_STATE(state, 1);
}
void Foo::state1()
{
ASSIGN_STATE(state, 2);
}
void Foo::state2()
{
;
}
void Foo::poll()
{
(this->*state)();
}
Foo::Foo()
{
this->init();
}
我安装了一个具有全局作用域的此类对象:
Foo foo;
int main()
{
foo.init();
while(1)
foo.poll();
return(1);
}
如果我编译项目,其他方法(state1()
和state2()
)没有直接调用的方法不会链接,并且固件在调用它们时会崩溃。
相反,如果我在main()
中实例化它们,则这些方法是链接的,并且一切都正常工作。
int main()
{
Foo foo;
foo.init();
while(1)
foo.poll();
return(1);
}
编译器和链接器标志:
COMPILER_FLAGS = $(DEBUG_FLAGS) -mcpu=cortex-m3 -mthumb -Wall -mlittle-endian -MD -MP -MF $(DEPS)/$(@F:%.o=%.d) -fno-strict-aliasing -fsigned-char -ffunction-sections -fdata-sections $(DEFINES) $(INCLUDES)
CPPCOMPILER_FLAGS = $(DEBUG_FLAGS) -mcpu=cortex-m3 -mthumb -Wall -mlittle-endian -MD -MP -MF $(DEPS)/$(@F:%.o=%.d) -fno-strict-aliasing -fsigned-char -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions $(DEFINES) $(INCLUDES)
LINKER_FLAGS = -mcpu=cortex-m3 -mthumb -specs=nano.specs -lnosys -L$(LINKERSCRIPT_DIR) -T$(LINK_SCRIPT) -Wl,--gc-sections $(DEFINES)
该项目是C/C++混合的。我使用GCC ARM TOOLS工具链在Windows7操作系统下进行编译。
我尝试使用不同的编译器标志和不同的优化选项,但没有任何变化。你知道我为什么会有这种行为,或者我该如何调查它的原因吗?
发生的情况是,您的部分代码被链接器收集到垃圾,因为它认为它在任何地方都没有被引用。我在只从ISR访问的代码中看到过这种情况,因为gcc看不到主代码和ISR之间的任何引用。
当您指定-ffunction-sections
和-fdata-sections
时,将为项目中的每个函数和数据项创建一个自动命名的部分。然后,当它到达链接器时,就得到了-Wl,--gc-sections
。这会导致链接器从输出中删除所有未引用的节。在MCU上,这是一件非常好的事情,因为它可以最大限度地减少程序内存的使用。不幸的是,正如我所描述的,编译器在检测未使用的代码时并不是绝对正确的。
在过去,我曾通过在代码中声明一个指向丢失对象的指针来解决这个问题,并确保我在主代码中初始化它。编译器看到传出引用,函数/数据不会被垃圾收集。
您还可以通过将丢失的数据/函数移动到一个从未使用gcc section
属性进行垃圾收集的部分来解决此问题。例如,要移动一个函数,可以在上面使用__attribute__((section(".text")))
。
- 使用类模板的方法链接错误
- 为什么调用没有正文的纯虚拟方法不会导致链接器错误?
- 在使用库时,找到要链接的必要库的快速方法是什么
- 尝试使用 extern "C" 调用 C 中的C++方法,得到"undefined reference to"对象的链接器错误
- 将多个效果与 libSox 链接并读取输出数据的正确方法
- 当只有静态方法受到影响时,如何解决C++中的链接器错误?
- 从方法链接中使用的临时移动
- 无法使用 Gradle 链接同一源文件中C++方法
- 为什么链接器报告全局函数的乘法定义符号,而不是类静态方法
- 使用 CMake 的静态方法链接错误
- gRPC trace.cc 的方法 TraceFlagList::Add(TraceFlag* flag) 使其链接列表
- 将枚举与 CMake 链接的正确方法是什么?
- 在没有额外代码的情况下链接两个独立类的最通用方法是什么?
- 在链接列表中添加字符串的简单方法
- 显式链接 DLL 和类方法
- 模板或链接接缝依赖注入有哪些替代方案来测试非虚拟方法?
- 为什么我不能在未链接的 DLL 上调用方法,但可以这样做?C++
- 同一对象的链接方法
- jni java.lang.unsatisfiedlinkerror,无法链接方法
- 如果不可用,避免链接方法