我正在维护一个自定义日志系统,它使用宏来做一些事情,比如将时间戳和源文件名附加到每条消息。所以就像这样:
AI_LOG("Hello %s", "World!");可能会导致:
(16.38) HelloWorld.cpp LOG: Hello World!目前,它在堆栈上创建一个char* buffer,将输出的初始部分放入缓冲区的开头,然后使用snprintf将输出复制到缓冲区的其余部分。这都行得通..。除了它在堆栈上创建缓冲区之外,如果我有一个足够深的堆栈和足够多的日志语句,而我没有保持很小的缓冲区(例如256个字符),我可能会得到堆栈溢出。我现在需要输出更长的字符串,所以将所有这些缓冲区放在堆栈上对我来说不再起作用。
考虑到这一背景...我想转到一个全局字符数组,我会把它做得很大(大概是4K字符)。然而,我的理解是,如果我只是说这样的话:
#define AI_OUTPUT_BUFFER_SIZE 4092
char AI_OUTPUT_BUFFER[AI_OUTPUT_BUFFER_SIZE];在我的输出系统的.h文件中,我冒着由包含该.h文件的每个文件创建单独的缓冲区的风险。这真的是个问题吗?如果是这样的话,有没有一个好的方法(编译器不可知,兼容C++98,不使用Boost)来获得我想要的单个缓冲区?
我倾向于在标题中这样做:
#define AI_OUTPUT_BUFFER_SIZE 4096
class AIOutputBuffer
{
public:
static char buffer[AI_OUTPUT_BUFFER_SIZE];
};然后在.cpp中,我可以:
char GAIA::AIOutputBuffer::buffer[AI_OUTPUT_BUFFER_SIZE];但这让我很头疼……也许我还没做对呢?
在人们建议之前..。是的,我可能会重写它以使用字符串或流...但我并不是真的想重写整个系统,我也没有时间和资源这样做。这个系统运行良好,给了我很大的灵活性--我只需要处理内存使用问题。
发布于 2016-05-17 01:42:40
来自评论(谢谢Dmitri!)我使用了extern,它就像一个护身符。因此,在标题中:
#define AI_OUTPUT_BUFFER_SIZE 256
extern char AI_OUTPUT_BUFFER[AI_OUTPUT_BUFFER_SIZE];然后在.cpp中:
char AI_OUTPUT_BUFFER[AI_OUTPUT_BUFFER_SIZE];发布于 2016-05-17 18:30:31
在您解决问题的同时,还有一个更好的解决方案,它依赖于std::string进行内存管理。此外,它在多线程环境中也能很好地工作。
我们的想法是使用老式的snprintf,但让std::string负责内存管理:
#include <string>
#include <cstdarg>
std::string va(const char* fmt, ...)
{
// make sure your stack can handle a one-time allocation of a buffer of this size
const auto BUFFER_SIZE = 8192;
// ...unless you know you're not going to call this from multiple threads;
// then you can make this buffer static and the size can be increased
char buffer[BUFFER_SIZE];
va_list args;
va_start(args, fmt);
std::vsnprintf(buffer, sizeof(buffer), fmt, args);
va_end(args);
buffer[sizeof(buffer) - 1] = '\0';
return buffer;
}用法:这里没什么特别的:auto logMsg = va("Hello %s", "World!");。
https://stackoverflow.com/questions/37258920
复制相似问题