X86_64环境
CentOS版本:CentOS Linux release 7.3.1611 (Core)
gcc 版本: 4.8.5 20150623 (Red Hat 4.8.5-28) (GCC)
gcc默认情况下char有符号,默认配置如下:
目标:x86_64-redhat-linux
配置为:../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,java,fortran,ada,go,lto --enable-plugin --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/cloog-install --enable-gnu-indirect-function --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux
代码测试:
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#define _GNU_SOURCE
#include <unistd.h>
#include <sys/syscall.h>
static int save_address[100];
static char call_idx = 0;
int main(void)
{
printf("PID=%d\n",(int)syscall(__NR_gettid));
while(1){
printf("eason call_idx=%d \n", call_idx);
save_address[call_idx++%100] = 1;;
}
}
编译:gcc -Wall -g main.c
[yubo.wang@localhost func-call]$ ./a.out
PID=82788
eason call_idx=0
eason call_idx=1
......
eason call_idx=127
eason call_idx=-128
段错误(吐核)
[yubo.wang@localhost func-call]$ gdb a.out core.82788
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-94.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/yubo.wang/4g-box/func-call/a.out...done.
[New LWP 82788]
Core was generated by `./a.out'.
Program terminated with signal 11, Segmentation fault.
#0 0x00000000004005f1 in main () at main.c:17
17 save_address[call_idx++%100] = 1;;
Missing separate debuginfos, use: debuginfo-install glibc-2.17-222.el7.x86_64
(gdb)
save_address[-28]怎么就引起进程崩溃退出了呢?查看上面的gdb信息可以看到触发了段错误,访问了非法内存,-28的内存地址是多少呢?
全局或静态局部变量容易(save_address[-25])引起访问非法内存,局部变量就不容易(save_address[-2095653])引起崩溃,这是为何?
需要看下《程序员的自我修养-链接、装载与库》才能解开心中疑惑啊。
编译时可添加参数设置char类型有无符号:-fsigned-char/ -funsigned-char
ARM_32环境
arm-linux-gnueabihf-gcc默认配置如下:
Configured with: /cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-linux/.build/src/gcc-linaro-4.9-2014.07/configure --build=i686-build_pc-linux-gnu --host=i686-build_pc-linux-gnu --target=arm-linux-gnueabihf --prefix=/cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-linux/install --with-sysroot=/cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-linux/install/arm-linux-gnueabihf/libc --enable-languages=c,c++,fortran --disable-multilib --enable-multiarch --with-arch=armv7-a --with-tune=cortex-a9 --with-fpu=vfpv3-d16 --with-float=hard --with-pkgversion='crosstool-NG linaro-1.13.1-4.9-2014.07 - Linaro GCC 4.9-2014.07' --with-bugurl=https://bugs.launchpad.net/gcc-linaro --enable-__cxa_atexit --enable-libmudflap --enable-libgomp --enable-libssp --with-gmp=/cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-linux/.build/arm-linux-gnueabihf/build/static --with-mpfr=/cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-linux/.build/arm-linux-gnueabihf/build/static --with-mpc=/cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-linux/.build/arm-linux-gnueabihf/build/static --with-isl=/cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-linux/.build/arm-linux-gnueabihf/build/static --with-cloog=/cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-linux/.build/arm-linux-gnueabihf/build/static --with-libelf=/cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-linux/.build/arm-linux-gnueabihf/build/static --enable-threads=posix --disable-libstdcxx-pch --enable-linker-build-id --enable-plugin --enable-gold --with-local-prefix=/cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-linux/install/arm-linux-gnueabihf/libc --enable-c99 --enable-long-long --with-mode=thumb --disable-multilib --with-float=hard
char类型默认无符号的,代码验证如下:
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#define _GNU_SOURCE
#include <unistd.h>
#include <sys/syscall.h>
static char call_idx = -1;
int main(void)
{
printf("PID=%d\n",(int)syscall(__NR_gettid));
if( call_idx < 0 ) {
printf("default signed call_idx=%d\n",call_idx);
}
else {
printf("default unsigned call_idx=%d\n",call_idx);
}
return 0;
}
root@www:~# ./a.out
PID=14177
default unsigned call_idx=255
这是为何呢? 难道与gcc版本有差异,原因未知。
其他类型默认都是有符号的,如:short,int,long。
所以在使用返回值类型定义时最好用int类型,防止默认无符号导致问题。
使用char类型时,最好使用typedef重定义,防止差异性,也会提高代码的移植性。