Question

I have a problem where I am trying to read words from stdin and then manipulate it and then print to stdout later. However, when I don't redirect the stdout, it segfaults at 2 places, if I'm trying to printf any words that I have scanned from STDIN (I can use puts() to display information to console that's fine though) OR when I try to access the inherent data from each words (like I strcasecmpr() that I used later). Can anyone here help?

int main(int argc, char** argv)
{
    int aflag = 0;
    int bflag = 0;
    int cflag = 0;
    int c;

    //int opteval
    Instruction head= NULL;
    Instruction first= NULL;
    init(head);
    puts("Init for head done");
    //While there are more instructions
    char line [128];
    printf("SdlJ");
    int numlines = 0;
    first = head; //Setting pointer to first instruction in list CHECK THIS LATER
    int index = 0;
    int rc = 0;
    char instr[20], r1[300], r2[300], r3[300], r4[300];
    instr[0] = '\0';
    r1[0] = '\0';
    r2[0] = '\0';
    r3[0] = '\0';
    r4[0] = '\0';

    while( fgets ( line, sizeof line, stdin) != NULL){
        puts(line);
        rc = sscanf(line, "%s %s %s %s %s", instr,r1,r2,r3,r4);
        if(rc == 4)
            puts("here");
        puts(instr);
        //printf("sfds%ssfsd", instr); SEGFAULT CASE 1: THIS WOULD SEG FAULT IF I UNCOMMENTED IT
        //return 1;
        chooseOp(head, instr);
        createReg(head, r1, 0);

        if(r2[0] != '=' && r2[0] != '\0')
            createReg(head, r2, 1);

        if(r3[0] != '='&& r3[0] != '\0')
            createReg(head, r3, 2);

        if(rc < 5)
            createReg(head, r4, 3);
        puts("here");
        Instruction next = NULL;
        init(next);
        numlines++;
        head->next = next;
        next->prev = head;
        head = next;
        //Point prevs's next to new head, and that heads prev to the previous head.
    }
}

void chooseOp(Instruction head, char* token){
    //Simple function to find the opcode responsible for this instruction
    //printf("sfdjls");

    puts("segfaulting");
    // SEGFAULT PLACE 2, IT SEGFAULTS RIGHT AT THIS STRCASECMP BELOW
    if(strcasecmp("nop", token) == 0){
        head->opcode= NOP;
        head->ismem=1;
        head->latency = 1;
    }
    else if(strcasecmp("addI", token) == 0){
        head->opcode= ADDI;
        head->ismem=1;
        head->latency = 1;
    }
    else if(strcasecmp("add", token) == 0){
        head->opcode= ADD;
        head->ismem=1;
        head->latency = 1;
    }
    else if(strcasecmp("subI", token) == 0){
        head->opcode= SUBI;
        head->ismem=1;
        head->latency = 1;
    }
    else if(strcasecmp("sub", token) == 0){
        head->opcode= SUB;
        head->ismem=1;
        head->latency = 1;
    }
    else if(strcasecmp("mult", token) == 0){
        head->opcode= MULT;
        head->ismem=1;
        head->latency = 3;
    }
    else if(strcasecmp("div", token) == 0){
        head->opcode= DIV;
        head->ismem=1;
        head->latency = 3;
    }
    else if(strcasecmp("load", token) == 0){
        head->opcode= LOAD;
        head->ismem=0;
        head->latency = 5;
    }
    else if(strcasecmp("loadI", token) == 0){
        head->opcode= LOADI;
        head->ismem=0;
        head->latency = 1;
    }
    else if(strcasecmp("loadAO", token) == 0){
        head->opcode= LOADAO;
        head->ismem=0;
        head->latency = 5;
    }
    else if(strcasecmp("loadAI", token) == 0){
        puts("here23");
        head->opcode= LOADAI;
        head->ismem=0;
        head->latency = 5;
    }
    else if(strcasecmp("store", token) == 0){
        head->opcode= STORE;
        head->ismem=0;
        head->latency = 5;
    }
    else if(strcasecmp("storeAO", token) == 0){
        head->opcode= STOREAO;
        head->ismem=0;
        head->latency = 5;
    }
    else if(strcasecmp("storeAI", token) == 0){
        head->opcode= STOREAI;
        head->ismem=0;
        head->latency = 5;
    }
    else if(strcasecmp("output", token) == 0){
        head->opcode= OUTPUT;
        head->ismem=0; //Need to ask prof about this
        head->latency = 1;
    }

    puts("here");
}

This is an example of what I'm supposed to read:

 loadI 1024     => r0 
 loadI 0    => r1 
 storeAI r1     => r0, 0 

And so on.

Please help.

EDIT: here's my code for init(head)

void init(Instruction head)
{
    head = (Instruction) malloc(sizeof(struct Command));
    head->opcode = 0;
    head->next = NULL;
    head->prev = NULL;
    head->ismem = -1;
    head->firstReg = NULL;
    head->secondReg = NULL;
    head->outputReg1 = NULL;
    head->outputReg2 = NULL;
    head->successors = NULL;
    //head->depends = NULL;
    head->numInstructions = 0;
    //head->lineNum = -1;
    head->priority = 0;
    head->numdepends = 0;
    head->cycle = 0;
    head->delay = -1;
}
Was it helpful?

Solution

This isn't going to turn into a giant debugging session, but this is a fundamental problem in your code and has to be resolved before anything else.

void init(Instruction head) // note: passed by-value
{
    head = (Instruction) malloc(sizeof(struct Command));
    // etc...
}

Consider this: Take a function that you want to use to set a caller-side int variable to some value. You'd do it like this:

void func(int *p) // note by-address
{
    *p = 42;
}

// caller code
int a = 0;
func(&a); // pass address

Pointers are no different. Pointers hold addresses, but the also have addresses (this distinguishes them from arrays, btw, which simply are addresses). Your init() should look like this:

void init(Instruction* head) // note: by address
{
    Instruction p = malloc(sizeof(struct Command)); // note no cast
    p->->opcode = 0;
    p->next = NULL;
    // etc...

    // save result to address given by out-parameter
    *head = p;
}

Caller side:

Instruction head = NULL;
init(&head); // note address passed.

This should get you going.


Side Note

C programmers like asterisks. Really. Not kidding. They're giant flags in the code that scream from the mountain-tops "THIS IS A POINTER". Hiding that in a typedef is rarely helpful. In fact there are only three cases I've seen where they are arguably legitimate, and one of those is a red-herring.

  1. An abtract opaque "handle" type for a library API. This is common and completely legitimate.
  2. Function pointer types. Often used to ensure proper types are being used for different "callback" mechanisms ( typedef int (*callback_type)(void); for example).
  3. Avoiding incorrect variable declarations on the same line. (this is the red herring).

The third of those is best demonstrated:

int* a,b; // declares one pointer-to-int, one int.

typedef int *int_ptr;
int_ptr a,b; // declared two pointers-to-int.

While that may seem helpful, it really isn't. The compiler will bomb when you try this later in the code:

*b = something;

So you'll catch yourself regardless (usually).

Bottom line, don't be afraid of asterisks. They're there to help you see things clearer if you let them.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top