为什么违反此代码的段

时间:2014-03-26 17:53:40

标签: c++ linux memory segmentation-fault

我正在使用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 有意思的是,关闭这个问题不是我想的。那好吧。我会把它留在这里几天,也许一周,所以在搜索中点击这个的人会看到解决方案。然后,我会删除。

0 个答案:

没有答案