c语言错误提示vc6,C语言VC6中使用asprintf, snprintf的坑

For VC6 C Users (not C++)

1. Explanation

You can't. You have to:

Guess a buffer size yourself.

Make a buffer that is large enough (which is not easy), then you can get a correct buffer size. See below.

snprintf enters the standard library in C99, and is not present in VC6. All you have is a _snprintf, which:

Returns -1 if the number of characters to write is less than or equal to count`. So can't be used to get the buffer size.

This seems not documentated (see Microsoft Docs). But _vsnprintf has special behavior in the same situation, so I guess there may be something here and with the test below I found my assumption correct.

Yes, it even doesn't return the number of characters it has written, like _vsnprintf. Just a -1.

This one is documentated: If buffer is a null pointer and count is nonzero, or if format is a null pointer, the invalid parameter handler is invoked, as described in Parameter Validation. invalid parameter handler is invoked means you will get a segmentation fault.

Test code here:

#includeintmain(void){chars[100],s1[100]={0};#defineTEST(s)printf("%s: %d\n",#s, s)TEST(_snprintf(NULL,0,"%d",12345678));/* Tested, and segmentation Fault */// TEST(_snprintf(NULL, 100, "%d", 12345678));TEST(_snprintf(s,0,"%d",12345678));TEST(_snprintf(s,100,"%d",12345678));TEST(_snprintf(s1,5,"%d",12345678));puts(s);puts(s1);return0;}

And the output with VC6 compiler:

_snprintf(NULL,0,"%d",12345678):-1_snprintf(s,0,"%d",12345678):-1_snprintf(s,100,"%d",12345678):8_snprintf(s1,5,"%d",12345678):-11234567812345

which supports my assumption.

Note that when the count argument passed in is smaller than the actual string length to write, though _snprintf returns -1, it will actually write count characters into the buffer.

2. Write one yourself with va_list? No way!

snprintf enters the standard library in C99, and there is no snprintf, _vsnprintf and __vscprintf:

asprintf.obj :error LNK2001:unresolved external symbol _vsnprintf

asprintf.obj :error LNK2001:unresolved external symbol __vscprintf

So you can't use the va_list implementation in one of the answers.

3. _vsnprint & _snprintf: Present but Absent

Actually, _vsnprintf is present. If you try to call it, you can make it.

You may say, there is a contradictory, you just said unresolved external symbol _vsnprintf. This is weird, but it's true. The _vsnprintf in unresolved external symbol _vsnprintf is not the one your code links to if you writes _vsnprintf directly.

Same thing happens on _snprintf. You can call it yourself, but you if you call snprintf, the linker will complain that there is no _snprintf.

4. Get the buffer size to write by passing 0 argument as count like we do in *nix? No way!

What's worse, you can't write this for yourself:

size_tnbytes =snprintf(NULL,0,fmt,__VA_ARGS__)+1;/* +1 for the '\0' */char*str =malloc(nbytes);snprintf(str,nbytes,fmt,__VA_ARGS__);

That's because:

As explained above, there is no snprintf in VC6.

As explained above, you can replace snprintf with _snprintf and compile it successfully. But since you passed NULL, you will get a segmentation fault.

Even if for some reason your program not crashed, nbytes will be -1 since you passed 0. And size_t is usually unsigned, so -1 will become a large number, like 4294967295 in an x86 machine, and your program will stop in the next malloc step .

5. Maybe an elegant solution

You can link a library called legacy stdio definitions or something else, but I choose to guess the buffer size myself, since in my case it is not very dangerous to do that.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值