分享一下最近做程序优化的一点小心得:在写高并发交易代码时要谨慎使用strncpy和sprintf。
下面详细介绍一下这样说的原因及建议实践:
1 慎用strncpy因为它的副作用极大
我们平时使用strncpy防止字符串拷贝时溢出,常常这样写
char buf[1024] = {0}; char str[16] = "hello"; strncpy(buf, sizefo(buf), str);
这样写当然没问题,但有些人不知道的是:strncpy一行代码执行时是往buf写了sizeof(buf) = 1024个字节,而不是直观以为的strlen(str) + 1 = 6个字符。
也就是说我们为了复制6个字符却写了1024个字节,多了不少额外消耗。如果这个函数被频繁调用,会导致系统性能出现不少损失。
因为调用strncpy(dest, n, str)时,函数首先将字符从源缓冲区str逐个复制到目标缓冲区dest,直到拷贝了n碰上 。
紧接着,strncpy函数会往buf填充 字符直到写满n个字符。
所以我才会说上面的代码strncpy才会写了1024个字节。
可以做一个小实验:
看上面代码及输出结果,我们可以知道在执行strncpy之前dest是用'1'填充的,但在执行strncpy后,前面几个字符变成hello,后面的字符全变成 ;
我个人的解决方法是写一个宏专用于往字符数组拷贝的,与大家分享一下,抛砖引玉。
// 静态断言 从vc拷贝过来(_STATIC_ASSERT) 稍微修改了一下 // 原来是typedef char __static_assert_t[ (expr) ] // 现在是typedef char __static_assert_t[ (expr) - 1 ] // 原因是gcc支持0字符数组 //TODO: 这里在win上编译有警告 有待优化 另外在linux宏好像不起作用 原因待查。暂时只有在win编译代码可以用 #ifndef _STATIC_ASSERT_RCC # ifdef __GNUC__ # define _STATIC_ASSERT_RCC(expr) typedef char __static_assert_t[ (expr) - 1 ] # else # define _STATIC_ASSERT_RCC(expr) do { typedef char __static_assert_t[ (expr) ]; } while (0) # endif #endif //将src复制到字符数组arr 保证不会越界并且末尾肯定会加 //_STATIC_ASSERT_RCC这里作用是防止有人传字符串指针进来 #define strncpy2arr(arr, src) do { char *dest_ = arr; size_t n = strnlen(src, sizeof(arr) - 1); _STATIC_ASSERT_RCC(sizeof(arr) != sizeof(char *)); memcpy(dest_, src, n); dest_[n] = '