0
votes

Good morning, Is it possible to fix Sun Solaris OS 5.8 segmention fault related to int * cast with gcc version 3.3? The gdb variable values are shown below. The cOrderedList class member variables are shown below. The uname -a and gcc -v outputa are shown below.
This code works fine on Windows Visual Studio C++ 9.0 .Thank you.

[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
Care to show the actual code that causes this? That is, the file cOrderedList.cpp the lines around line 272, maybe the whole LoadDatabaseRecords function if it's not to big. - Some programmer dude
Have you followed Rule of Three ? - Mahesh
@Joachim Pileborg, This code works fine on RedHat Linux 4.0 with gcc . I will try to post the post the code. Thank yoou. - Frank
@Joachim Pileborg, I just edited the post to include the code for LoadDatabaserecords. Thank you. - Frank
@Joachim Pileborg, This code works fine on RedHat Linux 4 with gcc version 4.1.2 . Thank you. - Frank

3 Answers

0
votes

Good afternoon, the problem turns out out not be a gcc code generation bug or a buffer over-run. The following solution was tested on Solaris a few minutes ago using this code:

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

Thank you for all of your answers and comments.

0
votes

Maybe this operation: "(Records+RecordCount*RecordSize+FieldOffsets[i])" is returning a value that is over the size of the records bounds.

It is hard to tell looking at only this portion of the code, but this may be caused by differences between the sizeof(char) in both platforms...

0
votes

A bit late, but none of the currently-posted answers address why the code posted fails.

This code

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

violates 6.3.2.3 Pointers, paragraph 7 of the C standard:

... A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned for the referenced type, the behavior is undefined. ...

Note that this code may also violate strict aliasing, but I haven't analyzed it closely enough to be certain. The fact that Records is a char * may allow for the aliasing to an int value. But even if the code is correct under strict aliasing, it still has to meet all underlying system alignment requirements for that int value, else it violates the restrictions of 6.3.2.3 above.

Not all systems allow the "address anything as anything" that's the de facto x86 standard. SPARC systems such as the one in this question do not allow such "anything goes" addressing.