valgrind - Issues with memcheck in C calculator -
i'm writing calculator in c
scratch (homework assignment) , have troubles memory somewhere.. algorithm works perfectly, i'm getting set of valgrind
errors/warnings, e.g.:
echo -n "1" | valgrind ./a.out --track-origins=yes
==14261== conditional jump or move depends on uninitialised value(s) ==14261== @ 0x400b9f: create_rpn (main.c:53) ==14261== 0x400742: main (main.c:253)
my makefile:
all: gcc main.c -g -o2 -wall -werror -std=c99
my source code below (and on github). can it? thank in advance!
#include <stdio.h> #include <stdlib.h> #include <string.h> #define max_len 1024 // needs check priority int get_power(char op) { if (op == '+') { return 2; } else if (op == '-') { return 2; } else if (op == '*') { return 4; } else if (op == '/') { return 4; } else { return 0; } } // checks if current char operator int is_operator(char op) { if (op == '+' || op == '-' || op == '*' || op == '/') { return 1; } else { return 0; } } // checks if current char digit int is_digit(char op) { if ((op >= '0' && op <= '9') || op == '.') { return 1; } else { return 0; } } // evaulates array in postfix double evaulate_rpn(char** exp, size_t len) { double* stack = (double* ) malloc(len*sizeof(double)); // stack operands double a1 = 0.0; double a2 = 0.0; // buffers save stack items size_t place = 0; // current stack size (size_t = 0; < len; ++i) { if (is_operator(*exp[i]) == 1) { // takes out last 2 operands, processes if (place > 1) { a1 = stack[place - 2]; a2 = stack[place - 1]; if (strncmp(exp[i], "+", 1) == 0) { stack[place - 2] = a1 + a2; } else if (strncmp(exp[i], "-", 1) == 0) { stack[place - 2] = a1 - a2; } else if (strncmp(exp[i], "*", 1) == 0) { stack[place - 2] = a1 * a2; } else if (strncmp(exp[i], "/", 1) == 0) { stack[place - 2] = a1 / a2; } place -= 1; } else if (place == 1) { // unary minus, unary plus.. a1 = stack[place - 1]; if (strncmp(exp[i], "-", 1) == 0) { stack[place - 1] = 0 - a1; } else if (strncmp(exp[i], "+", 1) == 0) { stack[place - 1] = a1; } } else { // wrong order / else printf("[error]"); exit(0); } } else { // operand -> convert char double -> save double stack stack[place] = atof(exp[i]); place++ ; } } float res = stack[0]; free(stack); return res; // result here } void push_to_stack(char*** reverse, size_t* inited_lines, size_t* used_lines, char* item, size_t size) { if(*inited_lines <= *used_lines){ *inited_lines *= 2; char** buf = (char** ) realloc(*reverse, (*inited_lines)*sizeof(char** )); if (buf) { *reverse = buf; } else { printf("[error]"); exit(0); } } char* str = calloc(size + 1, sizeof(char)); if (str) { memcpy(str, item, size + 1); str[size] = '\0'; (*reverse)[*used_lines] = str; (*used_lines)++ ; } else { printf("[error]"); exit(0); } } // transform infix postfix notation double create_rpn(char* exp, size_t len){ // stack of chars operands ()+-*/ char* stack = (char* ) malloc(len); if (stack == null) { printf("[error]"); exit(0); } size_t stack_top = 0; // position of last item in stack // array of numbers size_t inited_lines = 1; size_t used_lines = 0; char** reverse = (char** ) malloc(inited_lines*sizeof(char* )); if (reverse == null) { printf("[error]"); exit(0); } char buffer = 0; int bracket_deep = 0; int digit = 0; // flag start parsing numbers/digits size_t start_index = 0; // parsing long-vals size_t index = 0; while (index <= len) { buffer = exp[index]; // buffer constats 1 char string if (is_digit(buffer) == 1) { // save first digit place if (digit == 0) { start_index = index; digit = 1; } } else { // push stack when num on if (digit == 1) { digit = 0; size_t size = index - start_index; // size of str push_to_stack(&reverse, &inited_lines, &used_lines, exp + start_index, size); } // push operands + check priority if (is_operator(buffer) == 1) { size_t power = get_power(buffer); (int = stack_top - 1; >= 0; --i) { if (stack[i] == '(') { break; } if (get_power(stack[i]) >= power) { push_to_stack(&reverse, &inited_lines, &used_lines, &stack[i], 1); stack_top-- ; } } // push current operand stack stack[stack_top++ ] = buffer; } else if (buffer == '(') { stack[stack_top++ ] = buffer; bracket_deep++ ; } else if (buffer == ')') { // push operands result bracket_deep-- ; stack_top-- ; // if no, '' added output while (stack[stack_top] != '(') { push_to_stack(&reverse, &inited_lines, &used_lines, &stack[stack_top], 1); if (stack_top > 0) { stack_top-- ; } else { break; } } } else if (buffer == ' ' || buffer == '\n') { // ignore case } else if (buffer == '\0') { (int = stack_top - 1; >= 0; --i) { push_to_stack(&reverse, &inited_lines, &used_lines, &stack[i], 1); } stack_top = 0; } else { printf("[error]"); // - wrong char: '%s', %c\n", buffer, *buffer); // wrong char! exit(0); } } if (bracket_deep < 0) { printf("[error]"); // wrong bracket expr exit(0); } index++ ; } free(stack); if (bracket_deep == 0) { double res = evaulate_rpn(reverse, used_lines); (int = 0; < inited_lines; i++) { free(reverse[i]); } free(reverse); return res; } else { printf("[error]"); // wrong brackets exit(0); } } int main() { char* expression = (char* ) malloc(max_len*sizeof(char)); if (expression) { size_t len = 0; while (scanf("%c", &expression[len]) != -1) { // switch getch ??? if (expression[len] != ' ') { // save except spaces len++ ; } } double result = create_rpn(expression, len); printf("%.2f", result); free(expression); } else { printf("[error]"); exit(0); } return 0; }
you reading 1 byte beyond array bound, because while
loop in create_rpn()
is
while (index <= len)
but should be
while (index < len) /* ^ without = */
since arrays 0
indexed, exp[len]
beyond array.
also
avoid redundant parentheses, make code ugly , hence, hard read , understand.
do not cast return value of
malloc()
, read link , understand why.another tip make code clearer, avoid mixing code declarations, compiler it's easy see variable's scope, not eyes.
Comments
Post a Comment