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



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

[新LWP 1]程序接收到信号SIGSEGV,分段故障。cOrderedList::LoadDatabaseRecords中的0xff064b04(cSQLite*,char const*)(this=0x68f10、Database_=0xa4ba8,Command_=0xfbed468"SELECT*FROM LeftPattern")在/Source/cOrderedList.cpp:272272*((int*)(Records+RecordCount*RecordSize+FieldOffsets[i])=数据库_->ColumnInt(i);(gdb)打印i$3=3(gdb)打印记录$4=0xa0800"(gdb)打印RecordCount$5=0(gdb)打印RecordSize$6=50(gdb)打印字段偏移[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-aSunOS 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: %sn",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;
}

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

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

感谢您的回答和评论。

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

只看这部分代码很难判断,但这可能是由两个平台中的sizeof(char)之间的差异引起的。。。

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

此代码

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

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

。。。指向对象类型的指针可以转换为指向不同对象类型的指示器。如果结果指针没有正确对齐引用的类型,则行为未定义。。。

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

并非所有系统都允许"将任何东西作为任何东西来寻址",这是事实上的x86标准。像本问题中这样的SPARC系统不允许这样的"随用随用"寻址。

最新更新