【发布时间】:2018-06-02 06:44:04
【问题描述】:
几年前我开始了一个裸机 (Cortex-M) 项目。在项目设置中,我们决定使用启用 C++11 / C++14 等的 gcc 工具链,甚至使用 C++ 异常和 rtti。
我们目前正在使用gcc 4.9 from launchpad.net/gcc-arm-embedded(存在一些问题,导致我们目前无法更新到更新的 gcc 版本)。
例如,我写了一个这样的基类和一个派生类(另见运行示例here):
class OutStream {
public:
explicit OutStream() {}
virtual ~OutStream() {}
OutStream& operator << (const char* s) {
write(s, strlen(s));
return *this;
}
virtual void write(const void* buffer, size_t size) = 0;
};
class FixedMemoryStream: public OutStream {
public:
explicit FixedMemoryStream(void* memBuffer, size_t memBufferSize): memBuffer(memBuffer), memBufferSize(memBufferSize) {}
virtual ~FixedMemoryStream() {}
const void* getBuffer() const { return memBuffer; }
size_t getBufferSize() const { return memBufferSize; }
const char* getText() const { return reinterpret_cast<const char*>(memBuffer); } ///< returns content as zero terminated C-string
size_t getSize() const { return index; } ///< number of bytes really written to the buffer (max = buffersize-1)
bool isOverflow() const { return overflow; }
virtual void write(const void* buffer, size_t size) override { /* ... */ }
private:
void* memBuffer = nullptr; ///< buffer
size_t memBufferSize = 0; ///< buffer size
size_t index = 0; ///< current write index
bool overflow = false; ///< flag if we are overflown
};
以便我班的客户现在可以使用例如:
char buffer[10];
FixedMemoryStream ms1(buffer, sizeof(buffer));
ms1 << "Hello World";
现在我想让这个类的使用更舒适一些,并引入了以下模板:
template<size_t bufferSize> class FixedMemoryStreamWithBuffer: public FixedMemoryStream {
public:
explicit FixedMemoryStreamWithBuffer(): FixedMemoryStream(buffer, bufferSize) {}
private:
uint8_t buffer[bufferSize];
};
从现在开始,我的客户可以写:
FixedMemoryStreamWithBuffer<10> ms2;
ms2 << "Hello World";
但是从现在开始,我发现我的可执行二进制文件的大小越来越大。似乎 gcc 为 FixedMemoryStreamWithBuffer 的每个不同模板实例添加了符号信息(因为我们出于某种原因使用 rtti)。
有没有办法只为某些特定的类/模板/模板实例化去除符号信息?
可以为此获得一个非便携式 gcc 唯一的解决方案。
出于某种原因,我们决定更喜欢模板而不是预处理器宏,我想避免使用预处理器解决方案。
【问题讨论】:
-
如果去掉虚函数怎么办?只有多态对象才能使用 RTTI。
-
虚函数是绝对需要的,因为我还有一些其他类派生自
OutStream(例如 UartStream、TcpStream 等)。 -
只有在多态地使用这些派生类时才需要(即通过基类类型的表达式)。
-
operator <<在嵌入式系统中是一个糟糕的接口。它需要每种类型的实例来“流式传输”,因此您最终会在二进制文件中得到许多类似的序言/尾声。您应该尝试改用类似 printf 的解决方案(因为 va_list,尽管它们看起来很糟糕,但在二进制大小上却是相当理想的)。
标签: c++11 templates gcc bare-metal