GCC编译时char类型默认有无符号探索

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重定义,防止差异性,也会提高代码的移植性。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值