Сбивающая с толку обратная трассировка указывает на то, что произошел рекурсивный вызов, который не соответствует ожиданC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Сбивающая с толку обратная трассировка указывает на то, что произошел рекурсивный вызов, который не соответствует ожидан

Сообщение Anonymous »

Моя программа аварийно завершает работу очень редко, иногда только при срабатывании STR( — приостановить и возобновить работу программы в ОС QNX). Следующая обратная трассировка сбивает с толку, поскольку она указывает, что qnx_slog2::log_output() вызывает саму себя, что невозможно, поскольку соответствующий код не является рекурсивной функцией.
Обратная трассировка ниже меня действительно смущает.
  • Обратная трассировка сообщает, что qnx_slog2::log_output() вызывает сам себя, что невозможно, поскольку соответствующий код не функция рекурсии.
  • Адрес этого равен 0x2, когда qnx_slog2::log_output вызывается во второй раз, что не является допустимым адресом для экземпляра.

Код: Выделить всё

(gdb) bt
#0 0x0000003ae09b5cc0 in ?? ()
#1 0x0000001b5319cf64 in qnx_slog2::log_output (this=0x2, level=1, fmt=0x3ae09c9138 ,level=1)
at /home/jhone/qnx_slog2.hpp:137
#2 0x0000001b5319cf64 in qnx_slog2::log_output (this=0x1b531e9048 , level=1,
fmt=0x2ec2c7fbd0 "[st_slog2] 0MS-E oms_result_sender.cpp:174 operator()() soa ges dynamic rect width:0, height:0, x:0,y", level=1)
at /home/jhone/qnx_slog2.hpp:137
#3 0x0000003aed61fcc in malloc_lock.constprop.4 ()
from //home/jhone/publish/lib/libc.so.5
#4 0x6c757365725f736d in ??()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
Вот код qnx_slog2.hpp: строки с 128 по 149

Код: Выделить всё

void log_output(short level, const char* fmt, ...) {
if (true == log_block(level)) {
return;
}
std::unique_lock lock(lock_);
va_list args;
va_start(args, fmt);
switch (log_type_) {
case LOG_TYPE_QNX:
if ((fmt != nullptr) && (match_level(level) > 0) && (*fmt != '\0')) {   //line 137
vslog2f(nullptr, log_id_, match_level(level), fmt, args);
}
break;
case LOG_TYPE_PRINTF: {
memset(print_buffer_, 0, sizeof(print_buffer_));
vsnprintf(print_buffer_, sizeof(print_buffer_), fmt, args);
log_print(level);
break;
}
}
va_end(args);
}
Согласно официальному документу, vslog2f является потокобезопасным.
Благодаря совету @Retired Ninja.
slog2_set_default_buffer вызывается первым при инициализации экземпляра. Вот соответствующий фрагмент кода:

Код: Выделить всё

class qnx_slog2 {
private:
short log_type_ = LOG_TYPE_QNX;
short log_level_ = LOG_DEBUG;
int log_page_num_ = 4;
int log_id_ = 116;
std::mutex lock_;
char print_buffer_[1024] = {0};
slog2_buffer_t buf = {0};
public:
bool init() {
if (log_type_ != LOG_TYPE_QNX) {
return true;
}
std::unique_lock lock(lock_);
slog2_buffer_set_config_t config{};
config.buffer_set_name = __progname;
config.num_buffers = 1;
config.verbosity_level = SLOG2_DEBUG1;
config.buffer_config[0].buffer_name = LOG_TAG;
config.buffer_config[0].num_pages =
log_page_num_;  // one page 4KB
if (0 == slog2_register(&config, &buf, SLOG2_DISCARD_NEWLINE)) {
slog2_set_default_buffer(buf);
return true;
}
return false;
}
//omit not important code
}
Ответ на потенциальную проблему, заключающуюся в том, что спецификатор формата не соответствует типу аргумента.
Это не так. возможно, поскольку все сообщения журнала генерируются библиотекой fmt, которая широко используется spdlog и т. д. Другими словами, как указывает обратная трассировка, входные аргументы для qnx_slog2:: log_output всегда: короткий уровень, за которым следует const char*, и не более того. Ниже приведен простой фрагмент кода, чтобы его было легче понять. .

Код: Выделить всё

std::string log_msg = fmt::format(" soa ges dynamic rect width:{}, height:{}, x:{},y:{}", width, height, loc_x, loc_y);
qnx_slog2::get_instance().log_output(log_level, log_msg.c_str());
Может ли кто-нибудь пролить свет на то, как шаг за шагом решить эту проблему? Я действительно не знаю, что делать в первую очередь.
Обновить реализацию

Спасибо всем из вас.
Сначала в проекте использовался spdlog, а позже нам необходимо использовать slog2, который предоставляется самим QNX. Таким образом, во всех форматах журналов используется {}, кроме %d, одинаково. Требуется много работы, чтобы выполнить замену одну за другой.
Именно поэтому мы до сих пор используем fmt в качестве инструмента форматирования, а затем передаем форматированную строку в метод qnx_slog2::log_output.
Я согласен с Red.Wave, slogc — лучший выбор для этого условия. Я изменяю реализацию qnx_slog2::log_output и макросы, которые его вызывают, как показано ниже.
ПРИМЕЧАНИЕ: Поскольку в официальном документе говорится что slogc является потокобезопасным, поэтому я больше не использую std::mutex в реализации.

Код: Выделить всё

    void qnx_slog2::log_output(short level, const std::string& str) {
if (true == log_block(level)) {
return;
}

if (str.empty()) {
return;
}

slog2c(nullptr, log_id_, match_level(level), str.c_str());
}

void qnx_slog2::log_output(short level, const char* ptr) {
if (true == log_block(level)) {
return;
}

slog2c(nullptr, log_id_, match_level(level), ptr);
}

#define LOG_COMMON(log_level, log_level_str, fmt_log, ...)                                         \
do {                                                                                           \
try {                                                                                      \
auto fmt_str = fmt::format("[" LOG_TAG "] [" log_level_str "] {}:{} {}() " fmt_log,    \
__BASEFILE__, __LINE__, __func__, ##__VA_ARGS__);           \
qnx_slog2::get_log().log_output(log_level, fmt_str);                                   \
} catch (std::exception & e) {                                                             \
char internal_print_buffer[MAX_SIZE];                                                  \
int len = snprintf(internal_print_buffer, MAX_SIZE,                                    \
"[\" LOG_TAG \"] [CRITICAL] %s:%d %s() format error", __BASEFILE__,    \
__LINE__, __func__);                                                \
qnx_slog2::get_log().log_output(log_level, internal_print_buffer);                     \
}                                                                                          \
} while (0);

#define SERVICE_CRITICAL(fmt_log, ...) LOG_COMMON(LOG_CRITICAL, "SERVICE-C", fmt_log, ##__VA_ARGS__)
#define SERVICE_ERROR(fmt_log, ...) LOG_COMMON(LOG_ERROR, "SERVICE-E", fmt_log, ##__VA_ARGS__)
#define SERVICE_WARN(fmt_log, ...) LOG_COMMON(LOG_WARN, "SERVICE-W", fmt_log, ##__VA_ARGS__)
#define SERVICE_DEBUG(fmt_log, ...) LOG_COMMON(LOG_DEBUG, "SERVICE-D", fmt_log, ##__VA_ARGS__)
#define SERVICE_INFO(fmt_log, ...) LOG_COMMON(LOG_INFO, "SERVICE-I", fmt_log, ##__VA_ARGS__)
#define SERVICE_TRACE(fmt_log, ...) LOG_COMMON(LOG_INFO, "SERVICE-T", fmt_log, ##__VA_ARGS__)

#define ALG_CRITICAL(fmt_log, ...) LOG_COMMON(LOG_CRITICAL, "ALG-C", fmt_log, ##__VA_ARGS__)
#define ALG_ERROR(fmt_log, ...) LOG_COMMON(LOG_ERROR, "ALG-E", fmt_log, ##__VA_ARGS__)
#define ALG_WARN(fmt_log, ...) LOG_COMMON(LOG_WARN, "ALG-W", fmt_log, ##__VA_ARGS__)
#define ALG_DEBUG(fmt_log, ...) LOG_COMMON(LOG_DEBUG, "ALG-D", fmt_log, ##__VA_ARGS__)
#define ALG_INFO(fmt_log, ...) LOG_COMMON(LOG_INFO, "ALG-I", fmt_log, ##__VA_ARGS__)
#define ALG_TRACE(fmt_log, ...) LOG_COMMON(LOG_INFO, "ALG-T", fmt_log, ##__VA_ARGS__)

//omit simliar macros
Для новой модифицированной реализации (см. выше) программа аварийно завершает работу с гораздо меньшей вероятностью (около 1/(33×18), в то время как она составляет около 1(2 ×20) раньше) при срабатывании STR. Но обратная трассировка тоже выглядит странно.

Код: Выделить всё

#0  0x00000055f55b5afc in ?? ()
#1  0x0000004b6a42a9b8 in qnx_slog2::log_output (level=2, str=..., this=) at /mnt/nfs/qnx710/target/qnx7/usr/include/c++/v1/string:1520
#2  qnx_slog2::log_output (str=..., level=2, this=) at /home/jhone/qnx_slog2.hpp:103
#3  OMSResultSender::::operator()(void) const (__closure=) at /home/jhone/oms_result_sender.cpp:135
#4  0x0000004b6a42a9b8 in qnx_slog2::log_output (level=2, str=..., this=) at /mnt/nfs/qnx710/target/qnx7/usr/include/c++/v1/string:1520
#5  qnx_slog2::log_output (str=..., level=2, this=) at /home/jhone/qnx_slog2.hpp:103
#6  OMSResultSender::::operator()(void) const (__closure=) at /home/jhone/oms_result_sender.cpp:135
#7  0x0000000000000000 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
Советы:
1. Программа построен с помощью -g -O3 -DNDEBUG -std=gnu++14. Почему есть и -g, и -O3? Поскольку это релизная версия, опция -g добавляется постоянно, независимо от версии.
2. обратная трассировка выглядит так, как будто три функции были вызваны дважды (

Код: Выделить всё

OMSResultSender::::operator()(void)
, qnx_slog2::log_output и затем снова qnx_slog2::log_output, повторите указанные функции еще раз).

Подробнее здесь: https://stackoverflow.com/questions/784 ... -not-as-ex
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»