开发者

Unexpected pointer randomly changes. Why would it change for? Breaks pointer arithmetic

开发者 https://www.devze.com 2023-01-17 09:24 出处:网络
Maybe I\'m being stupid but I can\'t figure out why a pointer is being changed in this function. I have included \"printf\" and \"puts\" to show the problem. The left braket pointer is changing and in

Maybe I'm being stupid but I can't figure out why a pointer is being changed in this function. I have included "printf" and "puts" to show the problem. The left braket pointer is changing and invalidates the pointer arithmetic I want to do for string manipulation.

Another question I have - Is it dangerous to expect char pointers to remain constant for the same string when using C functions and do the pointers always point to addresses in a contiguous manner for strings? I can see problems arising with those concerns.

Edit: "//Changes here" placed to function which appears to change the point under my debugging.

char * py_to_c_expr(char * py_expr,int line,bool do_brakets){
    //Recursively converts python expression for use in C
    /*
     Order of evaluation. Top done last
     lambda - Not implemented yet
     if – else - Not implemented yet
     or
     and
     not
     in, not in, is, is not, <, <=, >, >=, <>, !=, == - in, not in and is not, not implemented yet
     |
     ^
     &  Bitwise AND
     <<, >>
     +, -
     *, /, //, %
     +x, -x, ~x - Positive useless
     **
     x[index], x[index:index], x(arguments...), x.attribute - Not implemented yet
     (expressions...), [expressions...], {key:datum...}, `expressions...` - Not implemented yet
     */
    char * find;
    //Convert "or", "and" and "is" to other characters to prevent conversion output confliction during processing
    char * scan;
    if (do_brakets) {
        py_expr = str_replace(py_expr, "or", "OR");
        py_expr = str_replace(py_expr, "and", "AND");
        py_expr = str_replace(py_expr, "is", "IS");
        //Convert brakets
        int nest = 0; //Amount of brakets gone into for processing
        //Stack to keep track of braket positions
        char ** left_bracket_ptr_stack;
        int left_bracket_ptr_stack_size = 0;
        scan = py_expr;
        while (true) {
            char * prior_scan;
            prior_scan = scan;
            scan = strstr(scan, "(");
            if (scan) {
                scan++;
            }
            if (scan) {
                nest++;
                //Entered braket. Add start position to stack
                left_bracket_ptr_stack = realloc(left_bracket_ptr_stack, sizeof(char *)*left_bracket_ptr_stack_size);
                left_bracket_ptr_stack[left_bracket_ptr_stack_size] = scan;
                printf("During left bracket scan:\n\nLeft braket pointer - %lli\nPython expression pointer - %lli\n",left_bracket_ptr_stack[left_bracket_ptr_stack_size],py_expr);
                left_bracket_ptr_stack_size++;
                printf("Length of stack - %i\n\n\n",left_bracket_ptr_stack_size);
            }else{
                scan = prior_scan;
                scan = strstr(scan, ")");
                if (scan) {
                    scan++;
                }
                if (scan) {
                    if (!nest) {
                        printf("Error: On line %i an expression closes too many brakets",line);
                        exit(1);
                    }
                    nest--;
                    //Exited bracket, process expression for braket
                    puts("During right bracket scan and processing:\n\n");
                    int len = scan - left_bracket_ptr_stack[left_bracket_ptr_stack_size - 1];
                    char * inner_braket = malloc(sizeof(char) * (len - 1));
                    strncpy(inner_braket,left_bracket_ptr_stack[left_bracket_ptr_stack_size - 1],len - 1); //Changes here
                    char * bracket_expression = py_to_c_expr(inner_braket,line,true);
                    char * new_py_expr = malloc(sizeof(char) * (strlen(py_expr) - strlen(inner_braket) + strlen(bracket_expression)));
   开发者_如何学运维                 free(inner_braket);
                    printf("Left bracket pointer - %lli\n",left_bracket_ptr_stack[left_bracket_ptr_stack_size -1]);
                    printf("Length of stack - %i\n",left_bracket_ptr_stack_size);
                    printf("Python Expression pointer - %lli\n\n\n",py_expr);
                    strncpy(new_py_expr,py_expr,left_bracket_ptr_stack[left_bracket_ptr_stack_size - 1] - py_expr - 1);
                    new_py_expr[left_bracket_ptr_stack[left_bracket_ptr_stack_size- 1] - py_expr - 1] = '\0';
                    strcat(new_py_expr,bracket_expression);
                    free(bracket_expression);
                    strcat(new_py_expr,scan);
                    free(py_expr);
                    py_expr = new_py_expr;
                }else{
                    scan = prior_scan;
                    if (nest) {
                        printf("Error: On line %i an expression does not close all brakets",line);
                        exit(1);
                    }
                    break;
                }
            }
        }
    }
    //Find operators and replace them with the functions. Recursively process each side.
    char * new_expr;
    scan = py_expr; //Reset scan to begining of the expression now that brakets are done
    scan = strstr(scan, "OR");
    if (scan) {
        char * left_side = malloc(sizeof(char) * (scan - py_expr + 1));
        char * right_side = malloc(sizeof(char) * (strlen(py_expr) - strlen(scan)));
        strncpy(left_side,py_expr,scan - py_expr);
        left_side[scan-py_expr] = '\0';
        strcpy(right_side,scan + 3);
        char * new_left_side = py_to_c_expr(left_side,line,false); //Recursively process left
        char * new_right_side = py_to_c_expr(right_side,line,false); //and right operands
        new_expr = malloc(sizeof(char) * (strlen(new_left_side) + strlen(new_right_side) + 5));
        strcpy(new_expr,"or(");
        strcat(new_expr,new_left_side);
        strcat(new_expr,",");
        strcat(new_expr,new_right_side);
        strcat(new_expr,")");
        return new_expr;
    }
    return py_expr;
}

Output:

During left braket scan:

Left braket pointer - 4296016033
Python expression pointer - 4296016032
Length of stack - 1


During left braket scan:

Left braket pointer - 4296016034
Python expression pointer - 4296016032
Length of stack - 2


During left braket scan:

Left braket pointer - 4296016035
Python expression pointer - 4296016032
Length of stack - 3


During right braket scan and processing:


Left braket pointer - 3473436750496411705
Length of stack - 3
Python Expression pointer - 4296016032


Program received signal:  “EXC_BAD_ACCESS”.

Thank you very much for any answer.


You're allocating one less pointer than you need here:

left_bracket_ptr_stack = realloc(left_bracket_ptr_stack, sizeof(char *)*left_bracket_ptr_stack_size);

(it should be (left_brack_ptr_stack_size + 1) that you multiply by).

In addition:

  • %p is the correct printf format string for printing pointers, not %lli;
  • strncpy() is not really a "safer strcpy()" - it is designed for filling fixed-length text fields, which means that it does not always nul-terminate the destination.
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号