是否可以使用gcc版本3.3修复与int * cast相关的Sun Solaris OS 5.8分段错误?

时间:2012-09-19 16:07:17

标签: c++ window solaris sparc

早上好,是否可以使用gcc 3.3版修复与int * cast相关的Sun Solaris OS 5.8分段错误? gdb变量值如下所示。 cOrderedList类成员变量如下所示。 uname -a和gcc -v outputa如下所示       此代码在Windows Visual Studio C ++ 9.0上正常工作。谢谢。

[New LWP 1]

Program received signal SIGSEGV, Segmentation fault.
0xff064b04 in cOrderedList::LoadDatabaseRecords(cSQLite*, char const*) (
    this=0x68f10, Database_=0xa4ba8,
    Command_=0xffbed468 "SELECT * FROM LeftPattern")
    at ../Source/cOrderedList.cpp:272
272      *((int*) (Records+RecordCount*RecordSize+FieldOffsets[i]))=Database_->ColumnInt(i);
(gdb) print i
$3 = 3
(gdb) print Records
$4 = 0xa0800 ""
(gdb) print RecordCount
$5 = 0
(gdb) print RecordSize
$6 = 50
(gdb) print FieldOffsets[i]
$7 = 46
class cOrderedList {
private:
    enum eFieldTypes {
        Character,
        Integer
    };

    bool CopyConstructed;

    int RecordCount;
    int FieldCount;
    int RecordSize;

    char *Records;
    int *FieldSizes,*FieldOffsets;
    eFieldTypes *FieldTypes;

    char *CurrentPos;
$ uname -a
SunOS 5.8 Generic_108528-22 sun4u sparc SUNW,Sun-Fire-V210

$ gcc -v
Reading specs from /usr/local/lib/gcc-lib/sparc-sun-solaris2.8/3.3/specs
Configured with: ../configure --disable-nls --with-as=/usr/ccs/bin/as --with-ld=
/usr/ccs/bin/ld
Thread model: posix
bool cOrderedList::LoadDatabaseRecords(cSQLite *Database_,const char *Command_) {
int retVal;
char str[4096];

RetrySQL:
RecordCount=0;
Database_->Prepare(Command_);
while ((retVal=Database_->Step())!=SQLITE_DONE) {
    switch (retVal) {
    case SQLITE_ROW:
        for (int i=0;i<FieldCount;i++) {
            if (FieldTypes[i]==Integer) {
                *((int*)   (Records+RecordCount*RecordSize+FieldOffsets[i]))=Database_->ColumnInt(i);
            } else {
                Database_->ColumnText(i,str);
                LTrim(str);
                RTrim(str);

                #if defined(_DEBUG)
                    if ((int) strlen(str)>=FieldSizes[i])
                        printf("Field not large enough: %s\n",Command_);
                #endif

                strncpy(Records+RecordCount*RecordSize+FieldOffsets[i],str,FieldSizes[i]);
                Records[RecordCount*RecordSize+FieldOffsets[i]+FieldSizes[i]-1]='\x0';
            }
        }
        RecordCount++;
        break;
    case SQLITE_BUSY:
        continue;
    case SQLITE_MISUSE:
        goto RetrySQL;
    default:
        break;
    }
}
return true;
}

3 个答案:

答案 0 :(得分:0)

也许这个操作:“(Records + RecordCount * RecordSize + FieldOffsets [i])”返回一个超过记录边界大小的值。

很难说仅查看代码的这一部分,但这可能是由两个平台中sizeof(char)之间的差异造成的......

答案 1 :(得分:0)

下午好,问题证明不是gcc代码生成错误或缓冲区溢出。几分钟前,使用以下代码在Solaris上测试了以下解决方案:

     int32_t x = Database->ColumnInt(i);
     memcpy(Records+RecordCount*RecordSize+FieldOffsets[i], &x, sizeof(int32_t));

感谢您的所有答案和评论。

答案 2 :(得分:0)

有点晚了,但是当前发布的答案都没有解决为什么发布的代码失败的原因。

此代码

            *((int*)   (Records+RecordCount*RecordSize+FieldOffsets[i]))=Database_->ColumnInt(i);

违反了6.3.2.3 Pointers, paragraph 7 of the C standard

  

...指向对象类型的指针可能会转换为指向其他对象类型的指针。如果生成的指针未针对引用的类型正确对齐,则行为未定义。 ...

请注意,此代码也可能违反strict aliasing,但我还没有对它进行足够详尽的分析才能确定。 Recordschar * 的事实可以允许将别名别名为int值。但是,即使代码在严格的别名下正确无误,它仍必须满足该int值的所有基础系统对齐要求,否则它违反了上面6.3.2.3的限制。

并非所有系统都允许使用x86标准的“把任何东西当作任何东西来寻址”。 SPARC systems such as the one in this question do not allow such "anything goes" addressing