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; }
编译
gcc -m32 test.cpp -o test
运行结果:
64位的测试用例:
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; }
编译:
gcc test.cpp -o test
运行结果:
可见,不管是32位还是64位,都存在问题。
修改方案是使用 memmove替代strncpy
strncpy(str2, str1+1, len-1); //strncpy(str1, str1+1, len-1); memmove(str1, str1+1, len-1);
非自身拷贝场景是正常的,比如把串a内容拷贝给串b,是正常的
strncpy(b, a, sizeof(b)-1);