我正在使用CentOS 6.5 64位。我正在运行的程序是用GCC(G ++)4.4.7编译的。当这是32位编译时,一切正常(通过这一点)。这是代码(只安排SCSI Write16命令):
void Write16::BuildCommand(UInt32 numSectors, UInt32 bz) {
buffSize_ = numSectors * bz;
if(pBuff_) {
delete [] reinterpret_cast<UInt8*>(pBuff_);
pBuff_ = NULL;
}
if(!pBuff_) pBuff_ = new UInt8[buffSize_]; // **Causes SEGV in 64-bits**
if(!pCdb_) pCdb_ = new UInt8[cdbLen16];
::memset(pCdb_, 0, cdbLen16);
FillRandom(pBuff_, buffSize_);
// code continues to set LBA and number of sectors
}
当执行到达我上面评论的那一行时,当编译为64位时,我得到了分段违规。使用numSectors = 1400和bz = 512调用Write16 :: BuildCommand;因此buffSize_ == 716800.显然,716800字节是来自堆的花生(这个系统有8GB的物理内存)。
我认为它可能与用户限制有关。这是ulimit -a的输出:
core file size (blocks, -c) unlimited
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 60209
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 32768
cpu time (seconds, -t) unlimited
max user processes (-u) 1024
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
我已经将我的堆栈大小提高到32mb(如果我没记错的话,那就是16)。但是,我的最大内存是无限的,虚拟内存也是如此。在这一点上,我很难过,想要第二眼。
修改 我发现了代码的问题。问题出在FillRandom()函数上。此函数使用random()库调用。我注意到这个函数的返回类型为 long int 。我的致命假设是long int总是4个字节宽。填充传入的数组如下:
void FillRandom(const void *pBuff, UInt32 size) {
// size is in bytes, convert to integer sized quantities
UInt32 numLongIntObjs = size / sizeof(long int); // if the area isn't quite divisible, oh well
long int * pTemp = reinterpret_cast<long int*>(const_cast<void*>(pBuff));
for(UInt32 i = 0; i < numLongIntObjs; i++) {
*pTemp = random();
pTemp++;
}
}
嗯,最初,代码看起来更像是这样:
void FillRandom(const void *pBuff, UInt32 size) {
// size is in bytes, convert to integer sized quantities
UInt32 numDwordObjs = size / 4; // *** OH NO, not good ***
long int * pTemp = reinterpret_cast<long int*>(const_cast<void*>(pBuff));
for(UInt32 i = 0; i < numDwordObjs; i++) {
*pTemp = random();
pTemp++;
}
}
而不是回答我自己的问题。我打算用这种方式编辑并干净地标记它关闭。
顺便说一句,我通过valgrind运行代码无意中发现了这一点。 Valgrind没有找到问题。事实上,Valgrind说它有自己的问题,并想提交一份错误报告。然而,在我确定为导致SEGV的代码之前很久,其中一篇关于错误的4字节写入的陈述引起了我的注意并引导我到这里。
编辑2 有意思的是,关闭这个问题不是我想的。那好吧。我会把它留在这里几天,也许一周,所以在搜索中点击这个的人会看到解决方案。然后,我会删除。