当前位置: 技术问答>linux和unix
一个超简单(仅5行语句的程序)却又莫名其妙的有趣问题,高手请进。
来源: 互联网 发布时间:2015-09-04
本文导语: #include int main(int argc, char *argv[]) { char str[25]=""; char sNum[256]; int *pNum=(int*)sNum; pNum[0]=1122; printf("%dn",pNum[0]); } 环境要求:HP-UNIX 这段程序以 aCC -g -o t t.cpp 编译(程序要支持C++的,所以要求用aCC编译) 为什么编译...
#include
int main(int argc, char *argv[])
{
char str[25]="";
char sNum[256];
int *pNum=(int*)sNum;
pNum[0]=1122;
printf("%dn",pNum[0]);
}
环境要求:HP-UNIX
这段程序以 aCC -g -o t t.cpp 编译(程序要支持C++的,所以要求用aCC编译)
为什么编译后运行,执行pNum[0]=1122;一句总是Bus error(coredump)?
问题出在哪里?而把字符串的初始化部分去掉就能正常运行。
能否不去掉初始化(甚至不改动源程序)就解决问题呢?
或者说为什么会出现这样的问题呢?
问题看似简单,却又奇怪,最好亲自试一下再发表看法。
|
str[25]没有自然对齐,你把它换成str[32]试试。
后面的语句不会有问题。
后面的语句不会有问题。
|
应该不是编译器的问题,而是HP机器体系结构的问题,某些64位机是不允许不对齐访问的,SUN的SPARC也是如此。所以写程序的时候要注意的。
|
还有此等怪事。仔细想了像,大概明白了。
char str[25];
char sNum[256];
这个编译器发现紧跟char str[25]后面的sNum为char类型,因此为了节约空间,并没有考虑将sNum的起始地址进行机器字节对齐。而后你又将sNum强制转换成int,然后这个CPU又不像Intel x86一样可以自动处理这种情况,结果出现bus error。
这种情况,我觉得编译器应该有个开关可以控制吧?
char str[25];
char sNum[256];
这个编译器发现紧跟char str[25]后面的sNum为char类型,因此为了节约空间,并没有考虑将sNum的起始地址进行机器字节对齐。而后你又将sNum强制转换成int,然后这个CPU又不像Intel x86一样可以自动处理这种情况,结果出现bus error。
这种情况,我觉得编译器应该有个开关可以控制吧?
|
bus error基本上是编译器对齐方式处理上造成的。也就是说pNum不是个int对齐的地址。
|
应该是内存对齐的问题,有些芯片不充许非偶的整数存取
或者这样定义
union { int n; char num[256]; } var;
v.n = 1122;
v.num[...] = ...
或者这样定义
union { int n; char num[256]; } var;
v.n = 1122;
v.num[...] = ...
|
不是编译器的问题
数组的内存是分配到栈里的,指针malloc的内存是分配到堆里的,int *pNum=(int*)sNum;这句的效用值的怀疑,一个分配到栈里的内存能否让你用一个指针随便去引用呢?
你可以这样啊
char ptr = new char[100];
int pNum = new ((int*)ptr) int(1122);
数组的内存是分配到栈里的,指针malloc的内存是分配到堆里的,int *pNum=(int*)sNum;这句的效用值的怀疑,一个分配到栈里的内存能否让你用一个指针随便去引用呢?
你可以这样啊
char ptr = new char[100];
int pNum = new ((int*)ptr) int(1122);
|
这是cpu的问题, 因为int的首地址需要是4的整数倍, 这样强制转换会导致这种core的
|
没有HP-UNIX,在windows平台用mingw的gcc编译运行没有问题
|
大概是aCC编译的问题吧,我在Linux和VC下都试过没问题。
没有HP,抱歉帮不上忙了。
没有HP,抱歉帮不上忙了。
|
和机器实现有关吧
把sNum强制转换成int*的,本来每个域是8个字节变成了32个字节,可能会报内存出错,所以会BUS ERROR
但有的实现计算的时候就是把char当成32位的.
把sNum强制转换成int*的,本来每个域是8个字节变成了32个字节,可能会报内存出错,所以会BUS ERROR
但有的实现计算的时候就是把char当成32位的.