Thread: Segfault and incompatible pointer types

  1. #1
    Registered User
    Join Date
    Oct 2015
    Posts
    5

    Segfault and incompatible pointer types

    Hello, I have been practicing C while making a project on it and for some reason I am getting an warning of incompatible pointer types and while on debugging I am getting a Segfault. I have checked all the functions for any errors that may crop up , but I have spend 8 hours trying to figure it out and still couldn't get any results. I don't have much experience in using gdb although I have tried to trace my error with it too. Any help is appreciated. It is seemingly impossible for me to solve this , typically due to lack of insight on the matter.

    Whole code is little bit big to post it all here ( probably ), however the source code is open.

    The source file: https://github.com/Mr-Kumar-Abhishek...xpr/zuzeelik.c

    The below code is in open license: https://github.com/Mr-Kumar-Abhishek/zuzeelik/blob/master/LICENSE

    Code:
    #include "mpc/mpc.h"
    
    // if compiling in windows, compiling with these functions 
    #ifdef _WIN32
    #include <string.h>
    
        static char buffer[2048];
    
        // fake readline functions 
        char* readline(char* prompt) {
            fputs(prompt, stdout);
            fgets(buffer, 2048, stdin);
            char* copy = malloc(strlen(buffer)+1);
            strcpy(copy, buffer);
            copy[strlen(copy) - 1] = '\0';
            return copy;
        }
    
        // fake add_history function 
        void add_history(char* not_used) {}
    
    // or include these editline header 
    #else 
    
        #include <editline/readline.h>
    
        // if not not OS X then include header file below
        #ifndef __APPLE__
            #include <editline/history.h>
        #endif
    
    #endif
    
    // creating enumeration of possible zval types 
    enum { ZVAL_NUMBER, ZVAL_ERROR, ZVAL_SYMBOL, ZVAL_SYM_EXRESSION };
    
    // Declaring new zval struct 
    typedef struct {
        int type;
        long number;
    
        // error and symbol types has some string data 
        char* er;
        char* sy;
    
        // count and pointer to the list "zval*" 
        int count;
        struct zval** cell;
    } zval;
    
    // constructing a pointer to a new number zval 
    zval* zval_number(long x) {
        zval* val = malloc(sizeof(zval));
        val->type = ZVAL_NUMBER;
        val->number = x;
        return val;
    }
    
    // constructing a pointer to a new error zval 
    zval* zval_error(char* err) {
        zval* val = malloc(sizeof(zval));
        val->type = ZVAL_ERROR;
        val->er = malloc((strlen(err) + 1));
        strcpy(val->er, err);
        return val;
    }
    
    // constructing a pointer new symbol type zval 
    zval* zval_symbol(char* sym){
        zval* val = malloc(sizeof(zval));
        val->type = ZVAL_SYMBOL;
        val->sy = malloc(strlen(sym + 1));
        strcpy(val->sy, sym);
        return val;
    }
    
    // constructing a pointer to new empty symbolic expressions 
    zval* zval_sym_expression(void) {
        zval* val = malloc(sizeof(zval));
        val->type = ZVAL_SYM_EXRESSION;
        val->count = 0;
        val->cell = NULL;
        return val;
    }
    
    void zval_delete(zval* val) {
        switch(val->type){
    
            // do nothing special for number type 
            case ZVAL_NUMBER: break;
    
            // if error or symbol free the string data 
            case ZVAL_ERROR:  free(val->er); break;
            case ZVAL_SYMBOL: free(val->sy); break;
    
            // if symbolic expression then delete all the elements inside 
            case ZVAL_SYM_EXRESSION: 
                for( int i = 0; i < val->count; i++ ) {
                    zval_delete(val->cell[i]);
                }
    
                // Also, free the memory contained in the pointers 
                free(val->cell);
            break;
        }
        
        // Lastly, free the memory for the zval struct itself 
        free(val);
    }
    
    zval* zval_read_number(mpc_ast_t* node) {
        errno = 0;
        long x = strtol(node->contents, NULL, 0);
        return errno != ERANGE ? zval_number(x) : zval_error( "Invalid number !");
    }
    
    zval* zval_increase(zval* val, zval* x){
        val->count++;
        val->cell =  realloc(val->cell, sizeof(zval*) * val->count);
        val->cell[val->count - 1] = x;
        return val;
    }
    
    zval* zval_read(mpc_ast_t* node) {
        
        // if symbol or number then returning to that type 
        if (strstr(node->tag, "number")) { return zval_read_number(node); }
        if (strstr(node->tag, "symbol")) { return zval_symbol(node->contents); }
    
        // if root (>) or sym-expression then creating a an empty list 
        zval* x = NULL;
        if(strcmp(node->tag, ">") == 0 ) { x = zval_sym_expression(); }
        if(strstr(node->tag, "sym_expression")) { x = zval_sym_expression(); }
    
        // Filling this list with valid expressions contained within
        for(int i = 0; i < node->children_num; i ++) {
            if ( strcmp(node->children[i]->contents, "(") == 0 ) { continue; }
            if ( strcmp(node->children[i]->contents, ")") == 0 ) { continue; }
            if ( strcmp(node->children[i]->contents, "regex") == 0 ) { continue; }
            x = zval_increase(x, zval_read(node->children[i]));
        }
        return x;
    }
    
    void zval_print(zval* val);
    
    void zval_expression_print(zval* val, char start, char end) {
        putchar(start);
        for(int i = 0; i < val->count; i ++) {
            // print the value contained within 
            zval_print(val->cell[i]);
    
            // don't print the trailing space if it is the last element
            if(i != val->count -1){
                putchar(' ');
            }
        }
        putchar(end);
    }
    
    // printing a zval 
    void zval_print(zval* val) {
        switch(val->type) {
    
            // in case the type is a number print it 
            // Also, then break out of the switch 
            case ZVAL_NUMBER: printf("%li", val->number); break;
            case ZVAL_ERROR: printf("Error: %s", val->er); break;
            case ZVAL_SYMBOL: printf("%s", val->sy); break;
            case ZVAL_SYM_EXRESSION: zval_expression_print(val, '(', ')'); break;
        }
    }
    
    // printing zval followed by a new line 
    void zval_println(zval* val){
        zval_print(val);
        putchar('\n');
    }
    
    // count total number of nodes 
    int number_of_nodes(mpc_ast_t* nodes) {
      if (nodes->children_num == 0) { return 1; }
      if (nodes->children_num >= 1) {
        int total = 1;
        for (int i = 0; i < nodes->children_num; i++) {
          total = total + number_of_nodes(nodes->children[i]);
        }
        return total;
      }
      return 0;
    }
    
    // using operator string to see which operation to perform 
    /*
    zval evaluate_o(zval x, char* o, zval y){
    
        // If any value is an error then return it 
        if ( x.type == ZVAL_ERROR ) { return x; }
        if ( y.type == ZVAL_ERROR ) { return y; }
    
        // otherwise doing calculations on number values 
        if(strcmp(o, "+") == 0 || strcmp(o, "add") == 0 ) { return zval_number( x.number + y.number ); }
        if(strcmp(o, "-") == 0 || strcmp(o, "sub") == 0 ) { return zval_number( x.number - y.number ); }
        if(strcmp(o, "/") == 0 || strcmp(o, "div") == 0 ) {
             
             //if the second operand is zero then returning an error
             return y.number == 0 ? zval_error( ZERROR_DIV_ZERO ): zval_number( x.number / y.number ); 
        }
        if(strcmp(o, "*") == 0 || strcmp(o, "mul") == 0 ) { return zval_number( x.number * y.number ); }
        if(strcmp(o, "%") == 0 || strcmp(o, "mod") == 0 ) {
            
            // Agian, if the second operand is zero then returning an error     
             return y.number == 0 ? zval_error( ZERROR_MOD_ZERO ): zval_number( x.number % y.number ); 
        }
        if(strcmp(o, "^") == 0 || strcmp(o, "pow") == 0 ) { return zval_number((pow(x.number,y.number))); }
        if(strcmp(o, "max") == 0 ){
            if (x.number<=y.number ){ return y; } else if(x.number>y.number){ return x; } 
         }
        if(strcmp(o, "min") == 0 ){
            if (y.number<=x.number) { return y; } else if(y.number>x.number){ return x; }
        }
        return zval_error( ZERROR_BAD_OP );
    }
    */
    /*
    zval evaluate(mpc_ast_t* node){
    
        // If tagged as number ... 
        if(strstr(node->tag, "number")){
            
            // checking if there is any error in conversion 
            errno = 0;
            long x = strtol(node->contents, NULL, 10);
            return errno != ERANGE ? zval_number(x) : zval_error( ZERROR_BAD_NUMBER );
        }
    
        // The operator is always second child 
        char* o = node->children[1]->contents;
    
        // initalizing for x to store third child, later on
        // by default a zval error of being a bad number 
        zval x = zval_error( ZERROR_BAD_NUMBER ); 
    
        // special case of getting only one negative number or expression 
        if ( node->children_num == 4 && strcmp(o, "-") == 0) {
            x = evaluate_o(zval_number(0), o, evaluate(node->children[2]));
        }else {
            // storing the third child in x 
             x = evaluate(node->children[2]);    
        }
        
        // Iterating the remaining children and combining (from fourth child) 
        int i = 3;
        while(strstr(node->children[i]->tag, "expr")){
            x = evaluate_o(x, o, evaluate(node->children[i]));
            i++;
        }
        return x;
    }
    */
    int main(int argc, char** argv) {
    
        // creating some parsers 
        mpc_parser_t* Number = mpc_new("number");
        mpc_parser_t* Symbol = mpc_new("symbol");
        mpc_parser_t* Sym_expression = mpc_new("sym_expression");
        mpc_parser_t* Expression = mpc_new("expression");
        mpc_parser_t* Zuzeelik = mpc_new("zuzeelik");
    
        // defining them with following language 
        mpca_lang(MPCA_LANG_DEFAULT,
            "                                                                                                       \
                number          : /-?[0-9]+(\\.[0-9]*)?/    ;                                                         \
                symbol       : '+' | '-' | '*' | '/' | '%' | '^' |                                                \
                              \"add\" | \"sub\" | \"mul\" | \"div\" | \"mod\" | \"max\" | \"min\"  | \"pow\"  ;      \
                sym_expression : '(' <expression>* ')' ;                                                          \
                expression   : <number> | <symbol> | <sym_expression> ;                                           \
                zuzeelik     : /^/ <expression>* /$/ ;                                                               \
            ",
        Number, Symbol, Sym_expression, Expression, Zuzeelik);
    
    
        puts("zuzeelik [ version: v0.0.0-0.3.0 ] \n");
        puts("Press Ctrl+C to Exit \n");
        
        // Starting REPL 
        while(1){
    
            // output from the prompt 
            char* input = readline("zuzeelik> ");
            
            // Add input to history 
            add_history(input);
            
            // An attempt to parse the input 
            mpc_result_t result;
            if(mpc_parse("<stdin>", input, Zuzeelik, &result)) {
    
                // On success print the Abstract Syntax Tree 
                printf("\nAbstract Syntax Tree:\n\n");
                mpc_ast_print(result.output);
                printf("\n\nTotal number of nodes: %i\n\n", number_of_nodes(result.output));
                
                // Print the evaluated answer 
            /*    printf("Evaluated output: ");
                zval answer = evaluate(result.output);
                zval_println(answer); */
                zval* x = zval_read(result.output);
                zval_println(x);
                zval_delete(x);    
                mpc_ast_delete(result.output); 
            }else {
    
                // Or else print the error 
                mpc_err_print(result.error);
                mpc_err_delete(result.error);
            }
    
            // free retrieved input 
            free(input);
        }
    
        // undefining and deleting parsers 
        mpc_cleanup(5, Number, Symbol, Sym_expression, Expression, Zuzeelik);
        return 0;
    }
    The branch I am trying this on:
    https://github.com/Mr-Kumar-Abhishek/zuzeelik/tree/s-expr


    Warnings from compiler:

    Code:
    cc -std=c99 -Wall zuzeelik.c mpc/mpc.c -ledit -lm -o zuzeelik
    zuzeelik.c: In function ‘zval_delete’:
    zuzeelik.c:99:5: warning: passing argument 1 of ‘zval_delete’ from incompatible pointer type [enabled by default]
    zuzeelik.c:86:6: note: expected ‘struct zval *’ but argument is of type ‘struct zval *’
    zuzeelik.c: In function ‘zval_increase’:
    zuzeelik.c:120:28: warning: assignment from incompatible pointer type [enabled by default]
    zuzeelik.c: In function ‘zval_expression_print’:
    zuzeelik.c:151:3: warning: passing argument 1 of ‘zval_print’ from incompatible pointer type [enabled by default]
    zuzeelik.c:145:6: note: expected ‘struct zval *’ but argument is of type ‘struct zval *’
    And from gdb:

    Code:
    Program received signal SIGSEGV, Segmentation fault.
    0x08048fc4 in zval_print ()
    (gdb) backtrace
    #0  0x08048fc4 in zval_print ()
    #1  0x08048f84 in zval_expression_print ()
    #2  0x08049048 in zval_print ()
    #3  0x0804905c in zval_println ()
    #4  0x08049213 in main ()
    git uri: https://github.com/Mr-Kumar-Abhishek/zuzeelik.git

    ( Clone recursively )
    Last edited by Mr.Kumar; 02-26-2016 at 11:24 PM. Reason: Fixed typo in heading, and added full source code

  2. #2
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    For the incompatible pointer in zval_delete, you need to give the struct a struct name (zval will do).
    Code:
    typedef struct {           //// should give the struct the name zval
        int type;
        long number;
    
        // error and symbol types has some string data 
        char* er;
        char* sy;
    
        // count and pointer to the list "zval*" 
        int count;
        struct zval** cell;   //// otherwise how does this work???
    } zval;
    It's interesting that you don't get a compiler warning.

  3. #3
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by algorism
    It's interesting that you don't get a compiler warning.
    No compiler warning because besides being a declaration of cell, this is also a forward declaration of struct zval that is presumably defined elsewhere:
    Code:
    struct zval** cell;
    The compile warning (or more likely compile error) is when people more commonly write:
    Code:
    zval** cell;
    but at that point the typedef has not happened, so zval is undeclared.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  4. #4
    Registered User
    Join Date
    Oct 2015
    Posts
    5
    Quote Originally Posted by algorism View Post
    It's interesting that you don't get a compiler warning.
    I was using GCC for compiling this.

    Code:
     
    root# gcc --version
    gcc (Ubuntu/Linaro 4.6.4-6ubuntu2) 4.6.4
    Copyright (C) 2011 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.  There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    
    root# cc --version
    cc (Ubuntu/Linaro 4.6.4-6ubuntu2) 4.6.4
    Copyright (C) 2011 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.  There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    Thank you for all the help, @algorism and thanks for providing me the insights about the compiler @laserlight
    Last edited by Mr.Kumar; 02-27-2016 at 02:07 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 12
    Last Post: 01-02-2009, 07:24 AM
  2. How to convert integral types into pointer types?
    By rohit99 in forum C++ Programming
    Replies: 3
    Last Post: 03-20-2008, 09:57 AM
  3. Segfault writing pointer-to-struct to file.
    By coolmoniker in forum C++ Programming
    Replies: 2
    Last Post: 02-05-2008, 12:56 AM
  4. Pointer types
    By jrfall349 in forum C Programming
    Replies: 8
    Last Post: 04-23-2007, 10:58 PM
  5. Replacing chars in Pointer String results in Segfault
    By discostu in forum C Programming
    Replies: 2
    Last Post: 03-08-2003, 03:38 PM

Tags for this Thread