pyt*_*hor 3 c printf segmentation-fault strlen
我有一个void *,叫它data,我知道它的长度,但不是空终止.我打这样的电话snprintf(line, sizeof(line), "%*s", n, (const char*)data),其中n已知的长度.几乎总是这样,但偶尔会导致段错误.
每当发生段错误时,后面跟踪表明问题出在strlen内部.当我data在gdb中打印时,我看到这样的东西
(gdb) p n
$1 = 88
(gdb) p (const char*) data
$2 = 0x1d752fa8
"JASDF" ... "ADS"<Address 0x1d753000 out of bounds>
(gdb) p 0x1d753000-0x1d752fa8
$3 = 88
Run Code Online (Sandbox Code Playgroud)
data确实是88个字符,但不是空终止,事实上,它似乎正好对着一个段.我的猜测是snprintf在数据上总是被称为strlen,我通常很幸运,即使data不是null终止,\0在我点击段之前还有一段时间我偶然发现它是不幸的.是对的吗?如果是这样,那是什么工作?
这就是堆栈跟踪的样子
#0 0x0000003c8927839e in strlen () from /lib64/libc.so.6
#1 0x0000003c89246749 in vfprintf () from /lib64/libc.so.6
#2 0x0000003c8926941a in vsnprintf () from /lib64/libc.so.6
#3 0x0000003c8924d0a3 in snprintf () from /lib64/libc.so.6
Run Code Online (Sandbox Code Playgroud)
编辑为了回答我自己关于解决方法的问题,strncpy是一个更适合调用的函数.我习惯使用snprintf.
snprintf(line, sizeof(line), "%*s", n, (const char*)data)
data是不是零终止?那你做错了.
snprintf(line, sizeof(line), "%.*s", n, (const char*)data);
Run Code Online (Sandbox Code Playgroud)
注意点.
在串的情况下,第一*中*.*如果所希望的输出(在屏幕上)长度-输入长度是第二*.man printf更多.
显然在%*s格式化的情况下可能会调用strlen(),因为它需要知道它是否需要填充输出以及如何填充它.
看起来你是对的.即使它不一定要在给定的上下文中,printf也不能保证不会调用strlen.你是通过提供一些非C字符串作为%s格式化说明符的参数而撒谎,所以你违反了合同printf.未定义的行为结果.