gcc4.8.5下strncpy的坑

   一直以来都很中意strncpy,没想到会在升级gcc版本后出现巨坑。

   使用场景是对串a开头几个字符做删除处理,假如有以空格开始的串,要求去掉空格,一般是自身拷贝,相当于对数组成员进行移位。

strncpy(a, a+n, strlen(a)-n)

像这个情况,在gcc4.8.5版本下,编译成32位及64位的应用,字符拷贝就会出问题。原因可能是gcc4.8.5的优化出现的问题。

centos7.4,gcc4.8.5实测如下:

复制代码
int main ()
{
  char str0[10]="123456789";
  char str1[512]= " IIP:123.112.154.118;LIP:192.168.118.107;MAC:54EE750B1713;HD:TF655AY91GHRVL23466SDGG;PCN:XXJSB-ZHUANGSHUANG;CPU:BFEBFBFF004065";
  char str2[240];
  char str3[40];
  int len = strlen(str1);
  /* copy to sized buffer (overflow safe): */
  strncpy (str2, str1+1, len-1);
  strncpy(str1, str1+1, len-1);
  str1[len-1] = 0;

  str3[5] = '\0';   /* null character manually added */

  puts(str1);
  puts (str2);
  puts (str3);

  return 0;
}
复制代码

编译

1
gcc -m32 test.cpp -o test

运行结果:

 

 64位的测试用例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int main ()
{
  char str0[11]="123456789";
  char str1[512]= " IIP:123.112.154.118;LIP:192.168.118.107;MAC:54EE750B1713;HD:TF655AY91GHRVL23466SDGG;PCN:XXJSB-ZHUANGSHUANG;CPU:BFEBFBFF004065";
   
  char str2[540];
  char *str3 = str2+1;
  int len = strlen(str1);
  printf("str0    [%p] str1[%p]str3[%p]\n", str0, str1, str3);
  strncpy (str3, str1, len);
  strncpy (str3, str3+1, len-1);
  strncpy(str1, str1+1, len-1);
  str1[len-1] = 0;
 
  puts(str1);
  puts (str2);
  puts (str3);
 
  return 0;
}

编译:

1
gcc test.cpp -o test

运行结果:

 

 可见,不管是32位还是64位,都存在问题。

修改方案是使用 memmove替代strncpy

1
2
3
strncpy(str2, str1+1, len-1);
//strncpy(str1, str1+1, len-1);
memmove(str1, str1+1, len-1);

  

非自身拷贝场景是正常的,比如把串a内容拷贝给串b,是正常的

1
strncpy(b, a, sizeof(b)-1);

  

posted @   超龄码农  阅读(673)  评论(0编辑  收藏  举报
编辑推荐:
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
· Linux系统下SQL Server数据库镜像配置全流程详解
阅读排行:
· Sdcb Chats 技术博客:数据库 ID 选型的曲折之路 - 从 Guid 到自增 ID,再到
· 语音处理 开源项目 EchoSharp
· 《HelloGitHub》第 106 期
· Huawei LiteOS基于Cortex-M4 GD32F4平台移植
· mysql8.0无备份通过idb文件恢复数据过程、idb文件修复和tablespace id不一致处
点击右上角即可分享
微信分享提示