Thread: prog runs on 64bit - seg faults on 32bit

  1. #1
    Registered User
    Join Date
    Dec 2006
    Posts
    8

    prog runs on 64bit - seg faults on 32bit

    Hi! I have a program (created a simple compiler using lex and yacc). I compile and run the program on my 64(SUSE) and it runs fine -- also worked for someone else on 64(Gentoo), but when I compiled and ran it on a 32-bit machine (CentOS) it seg faults. Could there just be an error in my program? Could this be compiler specific differences? Or is this just 32vs64? I'm not using ints much--I do declare a long in one spot. I would post the code, but very long and contains a very complex structure that is difficult to understand (at first glance anyway). I don't want to have to do that to you guys. Thanks in advance for any insight into this issue.

    Hollie

  2. #2
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    probably the problem with incorrect memory size allocated in some place causing memory overruns...

    Try to find out what part of the code is causing GPF (or by commenting out some parts, or debugging, or adding traces)
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  3. #3
    Registered User
    Join Date
    Dec 2006
    Posts
    8
    all my allocs either use sizeof() or I just do a strdup

  4. #4
    Registered User
    Join Date
    Dec 2006
    Posts
    8
    did try debugging with gdb
    found where. just can't figure out why. just the .y file is 490 lines so not good to post. Why would it run under 64 if the program is overrunning memory?

  5. #5
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    because on the 64-bit platform the pointer has size of 8
    on the 32-bit platform 4
    if you allocate memory base on pointer size
    but write then something based on int64 size you will succed on the first and fail on the second

    try to post the code where it fails
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  6. #6
    Registered User
    Join Date
    Dec 2006
    Posts
    8
    here is some of the more relevant code. It makes a parse tree in memory (each node is a operator that points to it's operands). ex() is called when the parse tree has been completely created.

    here are the declarations from the header file:
    Code:
    typedef enum { intType, fltType, symType, opType, regType } typeEnum;
    
    /* variables */
    typedef struct table_struct {
            char name[30];
            int declared;
            typeEnum type;
            union {
                    int  ival;
                    float fval;
            };
            struct table_struct *next;
    } symNode;
    
    /* numeric constants  */
    typedef struct numvalue {
            typeEnum type;
            union {
                    float fval;
                    int ival;
            };
    } numNode;
    
    /* operators */
    typedef struct operatorTag {
            typeEnum type;
            long value;
            int nops;
            struct nodeTypeTag *oprs[1];
    } opNode;
    
    /* generic node */
    typedef struct nodeTypeTag {
            typeEnum type;
            int reg;
            union {
                    symNode id;
                    numNode num;
                    opNode op;
            };
    } nodeType;
    here are all the functions that malloc with the exception of add_cmd which only does a strdup
    Code:
    /* called when I hit a numeric constant i.e. a number  */
    nodeType *con(numNode cnum) {
            nodeType *ptr;
            if ((ptr = malloc(sizeof(nodeType))) == NULL)
                    yyerror("out of memory");
            ptr->num.type = cnum.type;
            ptr->type = cnum.type;
            if (cnum.type == intType) {
                    ptr->num.ival = cnum.ival;
            }
            else
                    ptr->num.fval = cnum.fval;
            return ptr;
    }
    
    /* called when I encounter a variable name */
    nodeType *id(symNode *sym) {
            nodeType *ptr;
            char *cp;
            int len;
            char temp[30];
            typeEnum typ;
            if ((ptr = malloc(sizeof(nodeType))) == NULL)
                    yyerror("out of memory");
            typ = symType;
            ptr->id.type = sym->type;
            ptr->type = typ;
            len = strlen(sym->name);
            len = (len > 29) ? 29 : len;                               //prevent overflow (just in case)
            sprintf(ptr->id.name, "%-*.*s", len, len, sym->name);
            ptr->type = symType;
            typ = ptr->id.type;
            if (typ == intType)
                    ptr->id.ival = sym->ival;
            else
                    ptr->id.fval = sym->fval;
            return ptr;
    }
    
    /* 
    called when the statement is reduced  opSign would be like '+' or IF (#defined to a num)  nops is the number of operands 
    */
    nodeType *opr(long opSign, int nops, ...) {
            va_list ap;
            size_t size;
            int i;
            nodeType *ptr;
            size = sizeof(opNode) + ((nops) * sizeof(nodeType*));
            if ((ptr = malloc(size)) == NULL) {
                    yyerror("out of memory");
                    return NULL;
            }
            ptr->type = opType;
            ptr->op.value = opSign;
            ptr->op.nops = nops;
            va_start(ap, nops);
            for (i = 0; i < nops; i++) {
                    ptr->op.oprs[i] = va_arg(ap, nodeType*);
            }
            va_end(ap);
            return ptr;
    }
    
    /* this is the last to execute (parse tree is completely built)  before I free the memory this is where the segfault happens */
    
    int ex(nodeType *p) {
            int lbl1, lbl2;
            char cmd[50];
            char jmpCmd[5];
            int inc;
            int val;
            if (!p) return 0;
            switch(p->type) {
            case intType :
                    sprintf(cmd, "\tli $t%d, %d", p->reg,p->num.ival);
                    add_cmd(cmd);
                    break;
            case symType :
                    if (p->id.type == intType) {
                            sprintf(cmd, "\tlw $t%d, %s", p->reg, p->id.name);
                            add_cmd(cmd);
                    }
                    break;
            case opType :
                    val = (p->op.value == IF) ? 0 : 1;
                    switch (p->op.oprs[val]->op.value) {
                            case LT : sprintf(jmpCmd, "bge"); break;
                            case LTE: sprintf(jmpCmd, "bgt"); break;
                            case GT : sprintf(jmpCmd, "ble"); break;
                            case GTE: sprintf(jmpCmd, "blt"); break;
                            case EQL: sprintf(jmpCmd, "bneq"); break;
                            case NOTEQL: sprintf(jmpCmd, "beq"); break;
                    }
                    switch(p->op.value) {
                            case FOR :
                                    sprintf(cmd, "_LFOR%03d:", lbl1 = lblcnt++);
                                    add_cmd(cmd);
                                    sprintf(cmd, "\tli $t4, %d", p->op.oprs[1]->num.ival);
                                    add_cmd(cmd);
                                    sprintf(cmd, "\tsw $t4, %s", p->op.oprs[0]->id.name);
                                    add_cmd(cmd);
                                    sprintf(cmd, "\tli $s1, %d", p->op.oprs[2]->num.ival);
                                    add_cmd(cmd);
                                    sprintf(cmd, "\tlw $s0, %s", p->op.oprs[0]->id.name);
                                    add_cmd(cmd);
                                    sprintf(cmd, "\tbgt $s0, $s1, _EFOR%03d", lbl2 = lblcnt++);
                                    add_cmd(cmd);
                                    ex(p->op.oprs[3]);
                                    inc = (p->op.nops == 5) ? p->op.oprs[4]->num.ival : 1;
                                    sprintf(cmd, "\tli $t5, %d", inc);
                                    add_cmd(cmd);
                                    sprintf(cmd, "\tlw $s0, %s", p->op.oprs[0]->id.name);
                                    add_cmd(cmd);
                                    sprintf(cmd, "\tadd $s2, $s0, $t5");
                                    add_cmd(cmd);
                                    sprintf(cmd, "\tsw $s2, %s", p->op.oprs[0]->id.name);
                                    add_cmd(cmd);
                                    sprintf(cmd, "\tble $s2, $s1 _LFOR%03d", lbl1);
                                    add_cmd(cmd);
                                    sprintf(cmd, "_EFOR%03d:", lbl2);
                                    add_cmd(cmd);
                                    break;
                            case REPEAT :
                                    sprintf(cmd, "_LR%03d:", lbl1 = lblcnt++);
                                    add_cmd(cmd);
                                    ex(p->op.oprs[0]);
                                    ex(p->op.oprs[1]);
                                    sprintf(cmd, "\t%s $t2, $t3, _LR%03d", jmpCmd, lbl1);
                                    add_cmd(cmd);
                                    break;
                            case IF :
                                    ex(p->op.oprs[0]);
                                    if (p->op.nops == 3) {
                                            sprintf(cmd, "\t%s $t2,$t3,_L%03d", jmpCmd, lbl1 = lblcnt++);
                                            add_cmd(cmd);
                                            ex(p->op.oprs[1]);
                                            sprintf(cmd, "\tj _L%03d", lbl2 = lblcnt++);
                                            add_cmd(cmd);
                                            sprintf(cmd, "_L%03d:", lbl1);
                                            add_cmd(cmd);
                                            ex(p->op.oprs[2]);
                                            sprintf(cmd, "_L%03d:", lbl2);
                                            add_cmd(cmd);
                                    } else {
                                            sprintf(cmd, "\t%s L%03d $t2 $t3", jmpCmd, lbl1 = lblcnt++);
                                            add_cmd(cmd);
                                            ex(p->op.oprs[1]);
                                            sprintf(cmd, "L%03d:", lbl1);
                                            add_cmd(cmd);
                                    }
                                    break;
                            case ASSIGNMNT :
                                    p->op.oprs[1]->reg=0;
                                    ex(p->op.oprs[1]);
                                    sprintf(cmd, "\tsw $t0, %s",  p->op.oprs[0]->id.name);
                                    add_cmd(cmd);
                                    break;
                            default :
                                    if (p->op.value < 100) {                         //math expressions
                                            p->op.oprs[0]->reg=1;
                                            p->op.oprs[1]->reg=2;
                                    } else {                                        //relational expressions
                                            p->op.oprs[0]->reg=2;
                                            p->op.oprs[1]->reg=3;
                                    }
                                    ex(p->op.oprs[0]);
                                    ex(p->op.oprs[1]);
                                    /* ASCII Equilavants:  + 43, - 45, * 42, / 47, % 37   */
                                    switch (p->op.value) {
                                    case 43 : sprintf(cmd, "\tadd $t0, $t1, $t2"); add_cmd(cmd); break;
                                    case 45 : sprintf(cmd, "\tsub $t0, $t1, $t2"); add_cmd(cmd); break;
                                    case 42 : sprintf(cmd, "\tmul $t0, $t1, $t2"); add_cmd(cmd); break;
                                    case 47 : sprintf(cmd, "\tdiv $t0, $t1, $t2"); add_cmd(cmd); break;
                                    case 37 : sprintf(cmd, "\tdiv $t1, $t2\n\tmfhi $t0"); add_cmd(cmd); break;
                                    }
                    }
                    break;
            }
            return 1;
    }
    If it is a memory allocation error maybe it is in opr?
    really hard to debug because ex is recursive. I totally understand if no one wants to take the time to look at this. It is really nasty. But if you do and figure it out you will seriously be my personal HERO and ultimate master of C programming. THANKS!!!!!

  7. #7
    Registered User
    Join Date
    Dec 2006
    Posts
    8
    I checked and rechecked and rechecked. . .to make sure I'm passing the correct number of arguments, so pretty darn sure that is not the problem. In the opr() function the ptr->op.oprs[i] are of either type symType (for variables) or intType/fltType (for Numbers) and are allocated with id() and con() respectively.

  8. #8
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    the problem how you calculate size for the memory to be allocated

    the ptr is a pointer to nodeType
    that contains enum, int and opNode
    op Node is a struct that contains enum, long int and one pointer to nodeType
    you allocate memory for opNode and n pointers to nodeType
    and storing there NodeTypes and n pointers to nodeType
    so you allocate one pointer size bigger when you need but not allocate memory for enum and int

    On 64bit platforms it seems to be working, on 32 bit platform is actually not enough...

    maybe there other places where you miscalculate your memory
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  9. #9
    Registered User
    Join Date
    Dec 2006
    Posts
    8

    Exclamation

    yeah I did have it allocated as:
    Code:
    size = sizeof(opNode) + ((nops - 1) * sizeof(nodeType*));
    but that seg faulted even on the 64.

    this might be impossible to debug if you can't see everything.
    I probably have some nasty memory leak somewhere that is manifesting itself in different areas/ways.

    Could there be some kind of memory limited that is being excedeed? I also create a symbol table (array to pointers of symtype) and the array (100) of commands (add_cmd). I know there is an array max size, but didn't think that would be a problem for non-contiguous memory.

    After finals I'm going to roll up my sleeves and do some serious debugging (already spent over 10hr trying to debug though).

    Thank you so much for you help!!

  10. #10
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Well since you seem to be on linux, then I would suggest either of the following.

    1. Use valgrind.
    Advantage - you don't need a special executable built, but it will tell you a lot more about how memory is being used.

    2. Use electric fence.
    Electric fence is a dynamic memory debug tool which will trap at the first instruction which accesses illegal memory, as opposed to the normal case which traps when something unrelated notices the damage.
    Typical use
    gcc -g prog.c -lefence
    gdb a.out
    run

    The debugger should then point you to the line of code causing the initial memory corruption.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  11. #11
    Registered User
    Join Date
    Dec 2006
    Posts
    8

    Question

    these are all my memory allocs with the exception of add_cmd which just does a strdup on the parameter that is passed to it.

    why would allocating an extra node cause a seg fault? should I initialize that extra node to NULL just in case?

    besides:
    -not enough memory being allocated
    -freeing memory that has not been allocated
    -referencing memory that has not been allocated/initialized

    what else could cause a seg fault?

  12. #12
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    freeing twice the same memory
    using not initialized (or null) pointers
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  13. #13
    Registered User
    Join Date
    Dec 2006
    Posts
    8
    I'll try those debugging tools. I usually just used the high tech printf debugger approach (I'm sure you guys know the kind of errors that causes!) until my professor showed me gdb (he couldn't find it either, but he only looked at it for an hour). I'll try those that you suggested. Thanks so much!

    Could different versions of lex/yacc/gcc be causing the problem? I'll try to have another person with 32 run it and see what happens. . . .

  14. #14
    Registered User
    Join Date
    Jun 2004
    Posts
    201
    Not sure if this could cause a buffer overflow, but maybe worth checking out:
    ptr->id.name is 30 chars and you pass 2x len (29?)


    Code:
    len = strlen(sym->name);
    len = (len > 29) ? 29 : len;                               //prevent overflow (just in case)
    sprintf(ptr->id.name, "%-*.*s", len, len, sym->name);

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Why does CppUnit give me seg faults?
    By cpjust in forum C++ Programming
    Replies: 3
    Last Post: 05-20-2010, 03:00 AM
  2. Seg faults. structs. pointers.
    By ominub in forum C Programming
    Replies: 12
    Last Post: 05-03-2009, 07:04 PM
  3. Replies: 9
    Last Post: 02-03-2009, 05:40 PM
  4. Help with arrays and seg faults
    By IdioticCreation in forum C++ Programming
    Replies: 7
    Last Post: 04-03-2008, 03:16 PM
  5. sorted linked list...why seg faults!
    By S15_88 in forum C Programming
    Replies: 4
    Last Post: 03-24-2008, 11:30 AM