在AIX 6.1上,我有一段代码,argv
在调用NULL
后以某种方式设置为strdup
。完全相同的代码适用于Linux,HPUX和Solaris。
以下是我正在获取核心转储的生产代码的摘录:
Makefile
....
CFLAGS += -I$(SERVER)/shared/interfaces \
-DADAPTER_BUILD_DATE="\"$(shell date)\""
....
global.c
...
char *z_adapter_build_date = NULL;
...
shared.c
...
extern char *z_adapter_build_date;
...
test.c的
int main(int l_argc, char **l_argv)
{
char *lbasename;
char *ltmp;
z_adapter_build_date = (char *)ADAPTER_BUILD_DATE;
ltmp = strdup(l_argv[0]);
lbasename = basename(ltmp);
if ((zprogname = strdup(lbasename)) == NULL)
{
printf("strdup failed:\n");
exit(1);
}
....
$ dbx ./test
warning: tpm_builtin_fn.cc is newer than /xps/ceal_800/rel/server/lib/libsql.so
warning: trans_tux.cc is newer than /xps/ceal_800/rel/server/lib/libsql.so
warning: varmap.cc is newer than /xps/ceal_800/rel/server/lib/libsql.so
(dbx) [1] stop in main
(dbx)
(dbx) r 1
[1] stopped in main at line 113 in file "/u01/xps/800/src/test.c" ($t1)
113 z_adapter_build_date = (char *)ADAPTER_BUILD_DATE;
(dbx) p l_argv[1]
"1"
(dbx) n
stopped in main at line 115 in file "/u01/xps/800/src/test.c" ($t1)
115 ltmp = strdup(l_argv[0]);
(dbx) p l_argv[1]
(nil)
但是,可能是红鲱鱼,cc文件版本中存在不匹配,我猜这可能是其中一个原因。我不太确定是什么导致该值变为NULL。
答案 0 :(得分:1)
这看起来非常可疑:
-DADAPTER_BUILD_DATE=$(shell date)
,特别是与
结合使用时z_adapter_build_date = (char *)ADAPTER_BUILD_DATE;
你显然想要注明一个日期字符串,但我不知道你所呈现的内容会给你什么,因为我不知道哪里会有报价使ADAPTER_BUILD_DATE
的扩展成为字符串文字所需的标记。我不认为它会在Linux上编译,但是如果AIX上的date
命令返回一个全数字日期,那么它可能会在那里编译。您可以考虑捕获预处理的输出以查看实际发生的情况。
顺便说一句,请注意,如果-DADAPTER_BUILD_DATE
扩展为字符串文字,那么您就不需要将其转换为char *
。在文字衰减到指针后,它应该是它的类型。
无论如何,如果您尝试通过该宏注入字符串文字,那么您可能会在makefile中更像这样:
-DADAPTER_BUILD_DATE='"$(shell date)"'
双引号需要进入宏定义,但该选项需要通过shell引用删除。单引号保护引号删除中的双引号,而不是删除引号。 make
本身会忽略所有引号。
答案 1 :(得分:0)
如果z_adapter_build_date
是某个C ++对象,使得它的赋值触发函数调用(来自const char *
的赋值运算符等),那么它们中的某些函数可能会使用堆栈上的字符串缓冲区。正在被溢出,从而破坏main
中恰好溢出寄存器并进入堆栈帧的局部变量。