“memset”使结构导致printf打印结构成员超过其限制

时间:2015-12-25 13:23:40

标签: c struct gdb memset

我在一个非常大的C程序中观察到了这个问题。

结构声明是:

struct kc910InputParms {
    char inStream[71];
}

在程序中,当对此struct变量执行memset操作时,printf语句的打印时间超过其限制(即71个字符是限制)。请参阅下面在gdb中调试时获得的输出。

(gdb) s
cpyInParmsToCbl (in=0xffffb9f6, out=0x80ef320) at kc190Common.c:456
456       memset((void*)out, ' ', sizeof(kc910InputParms));
(gdb) printf "<%s>\n", out.inStream
<>
(gdb) n
458       strncpy(out->inStream+16, in->system_id,strlen(in->system_id));
(gdb) printf "<%s>\n", out.inStream
<                                                                       Pending>

请注意上面的内容:附加了7个额外字符作为“待定”,打印out.inStream最多78个字符。这在该计划的后续阶段引入了缺陷。

有人可以帮助我理解这种行为以及使用memset的正确方法(如果我做错了)?

如果发生这种情况是因为变量out.inStream尚未被空字符'\0'终止,那么我的问题是:为什么它在memset之前没有以相同的方式打印?

1 个答案:

答案 0 :(得分:2)

这是由于缺少终止nul。它之前工作的原因是由于编译器将内存区域设置为nuls,或者只是随机运气。

您还告诉strncpy只有字符串中的字符存在空间,因此它不会添加终止符。这是错误的做法。您应该告诉strncpy 目标中可用的字节数,而不是中有多少字符。在这种情况下54(70-16)。对于源长度超过54个字符的情况,您应该将最后一个字节显式设置为nul。

printf和其他C字符串函数对数组大小或内存分配一无所知,它们通过终止nul。因此,如果您没有它,它们将一直持续到找到一个,可能耗尽已分配的内存空间并导致未定义的行为。这就是为什么你输出超过71个字符的原因。