0

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

[新 LWP 1]

程序收到信号 SIGSEGV,分段错误。
cOrderedList::LoadDatabaseRecords (cSQLite*, char const*) 中的 0xff064b04 (
    这=0x68f10,数据库_=0xa4ba8,
    Command_=0xffbed468 "选择 * FROM LeftPattern")
    在../Source/cOrderedList.cpp:272
272 *((int*) (Records+RecordCount*RecordSize+FieldOffsets[i]))=Database_->ColumnInt(i);
(gdb) 打印我
3 美元 = 3
(gdb) 打印记录
$4 = 0xa0800 ""
(gdb) 打印记录计数
$5 = 0
(gdb) 打印 RecordSize
6 美元 = 50
(gdb) 打印 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;
$ unname -a
SunOS 5.8 Generic_108528-22 sun4u sparc SUNW,Sun-Fire-V210

$ gcc -v
从 /usr/local/lib/gcc-lib/sparc-sun-solaris2.8/3.3/specs 读取规范
配置:../configure --disable-nls --with-as=/usr/ccs/bin/as --with-ld=
/usr/ccs/bin/ld
线程模型: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;
}
4

3 回答 3

0

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

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

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

于 2012-09-19T20:38:59.083 回答
0

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

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

于 2012-09-19T16:36:37.933 回答
0

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

这段代码

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

违反6.3.2.3 指针,C 标准的第 7 段

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

请注意,此代码也可能违反严格的别名,但我没有对其进行足够仔细的分析以确定。Records这是 a的事实char * 可能允许对一个int值进行别名。但是即使代码在严格别名下是正确的,它仍然必须满足该int值的所有底层系统对齐要求,否则它违反了上面 6.3.2.3 的限制。

并非所有系统都允许“将任何东西作为任何东西”,这是事实上的x86 标准。 SPARC 系统(例如这个问题中的系统)不允许这种“随便”寻址

于 2018-11-15T18:49:05.347 回答