【发布时间】:2026-01-31 12:10:01
【问题描述】:
我知道这个问题之前可能已经被问过,但没有回答我在下面发布的查询。我试图弄清楚为什么下面的代码给出了错误(在其他版本的 GCC 中,一个警告)和 esp。如何解决这个问题?我是一位经验丰富的 C++ 程序员,但有时您确实需要寻求帮助。任何帮助表示赞赏。
[错误]:无法通过非平凡可复制类型“class std::basic_string”的对象
/// USE THE MACRO BELOW TO LOG A FORMATTED STRING (usage is exactly like printf(...) [ SEE HEADER FILE - TEMPLATE FUNCTION user_log_fmt(...) ]
#define LOG_TRACE_FMT(...) Logger::getInstance()->user_log_fmt(LOG_LEVEL_TRACE, __PRETTY_FUNCTION__, __FUNCTION__, __VA_ARGS__)
void main()
{
std::string linkName = getLinkName();
// THIS IS THE CALL THAT LEADS TO THE ERROR AT COMPILE-TIME
LOG_TRACE_FMT("\nLink-name: %s, Sent packet: SYS: %d, COMP: %d, LEN: %d, MSG ID: %d\n", linkName, msg->sysid, msg->compid, msg->len, msg->msgid);
}
///
/// Part of logger class (combines strings with argument for formatting)
///
template <typename ... Args>
void user_log_fmt(LOG_LEVEL level, std::string pretty_func, std::string func_name, std::string str_format, Args ... args)
{
if (m_LogLevel < level)
return;
std::string formatted_data = utils::Utils::string_format(str_format, args...);
// Do something with the formatted string..
}
///
/// Part of Utils library. This method does a printf type formatting.
///
template<typename ... Args>
static std::string string_format( const std::string& format, Args ... args )
{
size_t size = snprintf( nullptr, 0, format.c_str(), args ... ) + 1; // Extra space for '\0'
std::unique_ptr<char[]> buf( new char[ size ] );
snprintf( buf.get(), size, format.c_str(), args ... );
return std::string( buf.get(), buf.get() + size - 1 ); // We don't want the '\0' inside
}
错误在于上面的 snprintf 语句。
关于 g++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609 的警告:
警告:格式不是字符串文字,也没有格式参数 [-Wformat-security] size_t size = snprintf(nullptr, 0, format.c_str(), args ...) + 1;' ^
g++ (Raspbian 4.9.2-10) 4.9.2 上的错误
错误:不能通过“...”传递非平凡可复制类型“class std::basic_string”的对象 size_t size = snprintf(nullptr, 0, format.c_str(), args ...) + 1;
注意:我希望了解并解决此问题,但不提供编译器标志设置。我知道这可能与C有关 与 C++ 的兼容性。
谢谢!
【问题讨论】:
-
@SouravGhosh 感谢您的指出。但是 snprintf 确实与 C 有关,我将其标记为 C 的原因。内容存储为 c-string。
-
@Sammy 很好,但是恕我直言,这个问题是基于 C++ 语言寻求答案,C 和 C++ 并不相同。
-
这与 C++ 与 C 的兼容性有关,但与 C 语言无关 - 因此标记不合适。
-
@Sammy :这些错误是来自模板的声明,还是来自使用?如果是后者,您能否显示调用(以及所有相关的声明)。 Ubuntu 错误看起来像您正在拨打
string_format( "Hello World" );之类的电话。 Pi 错误看起来像std::string foo="foo"; string_format("Hello %s",foo); -
@Sammy --
snprintf是一个 C 函数,但您传递的内容只有 C++ 知道。这肯定不会可靠地工作。此外,如果我正确阅读了 C++ 标准的18.10.3,则传递任何不符合参数列表的内容都是未定义的行为。换句话说,如果您使用varargs函数(例如snprintf、printf等),您最好做纯粹的C或C兼容工作。