Доброе утро, возможно ли исправить ошибку сегментации Sun Solaris OS 5.8, связанную с int * cast с gcc версии 3.3? Значения переменной GDB показаны ниже. Переменные-члены класса cOrderedList показаны ниже. Uname -a и gcc -v outputa показаны ниже.
Этот код отлично работает на Windows Visual Studio C ++ 9.0. Спасибо.
[Новый LWP 1] Программа получила сигнал SIGSEGV, Ошибка сегментации. 0xff064b04 в cOrderedList :: LoadDatabaseRecords (cSQLite *, char const *) ( это = 0x68f10, база данных_ = 0xa4ba8, Command_ = 0xffbed468 "SELECT * FROM LeftPattern") на ../Source/cOrderedList.cpp:272 272 * ((int *) (Records + RecordCount * RecordSize + FieldOffsets [i])) = База данных _-> ColumnInt (i); (GDB) печать я $ 3 = 3 (GDB) печать записей $ 4 = 0xa0800 "" (gdb) печать RecordCount $ 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;
$ uname -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 / к.х.н. / бен / л.д. Модель потока: 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;
}
Добрый день, проблема оказывается не в ошибке генерации кода 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. Указатели, пункт 7 стандарта С:
… Указатель на тип объекта может быть преобразован в указатель на другой тип объекта. Если результирующий указатель не правильно выровнен для ссылочного типа, поведение не определено. …
Обратите внимание, что этот код также может нарушать строгое наложение, но я не проанализировал это достаточно близко, чтобы быть уверенным. Дело в том, что Records
это char *
может учесть псевдоним для int
значение. Но даже если код верен при строгом псевдониме, он все равно должен соответствовать всем базовым требованиям к системному выравниванию. int
значение, иначе это нарушает ограничения пункта 6.3.2.3 выше.
Не все системы допускают де-факто стандарт х86. Системы SPARC, такие как в этом вопросе, не разрешают такую адресацию «все идет».