我已经从互联网上下载并重新编译了一个图书管理员,由于非法指针地址而导致核心转储。
从源头看,所涉及的陈述是:
#define E_DEBUG(level, ...) \
if (err_get_debug_level() >= level) \
err_msg(ERR_DEBUG, FILELINE, __VA_ARGS__)
#define E_DEBUGCONT(level, ...) \
if (err_get_debug_level() >= level) \
err_msg(ERR_DEBUG, NULL, 0, __VA_ARGS__)
和崩溃的行:
E_DEBUGCONT(1, (" %d", i));
事实上,编译器正在警告它:
In file included from ptm_mgau.c:56:0:
ptm_mgau.c: In function ‘ptm_mgau_calc_cb_active’:
ptm_mgau.c:317:30: warning: left-hand operand of comma expression has no effect [-Wunused-value]
E_DEBUGCONT(1, (" %d", i));
^
/home/pma/actual/pocketsphinx/pocketsphinx-5prealpha/../sphinxbase-5prealpha/include/sphinxbase/err.h:142:37: note: in definition of macro ‘E_DEBUGCONT’
ptm_mgau.c:317:24: warning: passing argument 4 of ‘err_msg’ makes pointer from integer without a cast [-Wint-conversion]
E_DEBUGCONT(1, (" %d", i));
^
/home/pma/actual/pocketsphinx/pocketsphinx-5prealpha/../sphinxbase-5prealpha/include/sphinxbase/err.h:142:37: note: in definition of macro ‘E_DEBUGCONT’
/home/pma/actual/pocketsphinx/pocketsphinx-5prealpha/../sphinxbase-5prealpha/include/sphinxbase/err.h:159:1: note: expected ‘const char *’ but argument is of type ‘int’
err_msg(err_lvl_t lvl, const char *path, long ln, const char *fmt, ...);
编译器非常准确:在表达式中( " %d", i )
表示忽略"%d"
并导致i
的值。后者,这个我被用作指针,导致崩溃。
代码的作者似乎期望宏扩展产生这一行:
if (err_get_debug_level() >= level) \
err_msg(ERR_DEBUG, NULL, 0, " %d", i)
但预处理器产生:
if (err_get_debug_level() >= level) \
err_msg(ERR_DEBUG, NULL, 0, ( " %d", i) )
有什么方法可以解决这个问题,更改宏定义而不是逐个遍历所有DEBUG语句(数百个)?
**附录**
重现问题的最小例子是编译并执行以下代码:
#include <stdio.h>
#include <stdarg.h>
#define ERR_DEBUG 1
#define FILELINE __FILE__ , __LINE__
void err_msg(int lvl, const char *path, long ln, const char *fmt, ...) {
char msg[1024];
va_list ap;
va_start(ap, fmt);
vsnprintf(msg, sizeof(msg), fmt, ap);
va_end(ap);
printf("%s\n",msg);
}
#define E_DEBUG(level, ...) \
err_msg(ERR_DEBUG, FILELINE, __VA_ARGS__)
int main ( void ) {
E_DEBUG(1,("%d",14));
}
答案 0 :(得分:0)
像
这样的东西#define PASTE(...) __VA_ARGS__
/*PASTE __VA_ARGS__ */
将删除括号,但它取决于总是的括号。
应用于您的示例:
#define PASTE(...) __VA_ARGS__
#define E_DEBUG(level, ...) \
if (err_get_debug_level() >= level) \
err_msg(ERR_DEBUG, FILELINE, PASTE __VA_ARGS__)
#define ERR_DEBUG 1
#define FILELINE __FILE__ , __LINE__
int err_get_debug_level(void);
void err_msg(int lvl, const char *path, long ln, const char *fmt, ...);
int main ( void ) {
E_DEBUG(1,("%d",14));
}
编译。