#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2012
    Posts
    3
    Rep Power
    0

    Angry RPN Calculator: *** glibc detected *** ./ufmg: malloc(): memory corruption: 0x08c123d


    So... I was all happy that have finished my college project at work, only to find it wouldn't compile for nothing on my Ubuntu platform.

    After the eight iteration of the main loop, where the program reads and treats a string from a file, i get this *** glibc detected *** ./ufmg: malloc(): memory corruption: 0x08c123d0 *** error.

    here is the code:

    main.c:
    PHP Code:
    /**********************************
     *Feito por: Gabriel Chamon Araujo*
     **********************************
     *Matricula: 2012018194             *
     **********************************
     *AEDS II* Turma M1 * 18/09/2012  *
     **********************************
      *
      *    Multi String RPN Calculator
      *        por Gabriel Chamon Araujo.
      *
      *    como proposto na descrição do TP0, o programa foi escrito
      *        com o objetivo de se calcular expressões matemáticas des-
      *        critas na notação polonesa reversa.
      *
      *    para tal ele se utiliza de funções de tratamento de string
      *        assim como se preocupa em otimizar a memoria.
      *
      * não há qualquer interação com o usuário, apenas é lido um
      *     arquivo entrada.txt com as expressões e o programa cria
      *     um arquivo saida.txt com os resultados.
      *
      * são reconhecidas as operações de Adição, Multiplização, Di-
      *     visão, Subtração, Exponete e Módulo. Para se utilizar
      *     a função módulo foi necessario um casting (int) nos ter-
      *        mos operados.
      */

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include "house.h"

    int main(int argcchar** argv) {

        
    FILEpIn;
        
    FILEpOut;

        
    charnameEntry;
        
    charnameExit;

        
    int option;

        while ((
    option getopt (argcargv"i:o:")) != -1) {

            switch(
    option) {
                case 
    'i':    nameEntry optarg;
                            break;
                case 
    'o':    nameExit optarg;
                            break;
            }

        }

        
    pIn openfile(nameEntry"r");
        
    pOut openfile(nameExit"w+");

        
    Solve(pInpOut);

        
    fclose(pIn);
        
    fclose(pOut);

        return 
    0;


    house.c
    PHP Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    #include <math.h>
    #include "house.h"

    /*Custom open file procedure, with error display*/
    FILEopenfile(charfileNamecharmode) {

        
    FILEfooFile//generic file name

        
    fooFile fopen(fileNamemode);

        if (
    fooFile == NULL) {
            
    printf("%s "fileName);
            
    perror("Error");
            exit(
    1);
        }
        else
            return 
    fooFile;

    }

    /*Explicit matrix memory release function*/
    void freemat(float** mint columns) {

        
    int i;

        for (
    i=0i<columnsi++)
                
    free(m[i]);
        
    free (m);

    }

    /*Generic matrix memory allocation funcion*/
    float** allocmat(int linesint columns) {

        
    int i;
        
    float** m;

        
    m=(float**) malloc (lines*sizeof(float*));
        if(!
    m) exit(1);
        for (
    i=0;i<lines;i++){
            
    m[i]=(float*) malloc (columns*sizeof(float));
            if(!
    m[i]) exit(1);
        }

        return 
    m;

    }

    /*Extract one line at a time from file and puts it into a char string*/
    charbuildCommandLine(FILEpFile) {

        
    charbuffer//will contain the optimized string
        
    chartemp//will contain a raw string

        
    temp = (char*) malloc (sizeof(char)*256);
        if (
    temp == NULL) exit(1);

        
    temp fgets(temp256pFile);

        
    /*memory optimizing procedures*/
        
    buffer = (char*) malloc (sizeof(char)*strlen(temp));
        if(
    buffer == NULL) exit(1);
        
    strcpy(buffertemp);

        
    free(temp);

        return 
    buffer;
    }

    /*checks whether the command line follows default command structure given by
        amount of operands being the amount of numbers less 1
        also checks null entry lines*/
    int parseCommand(charstrintnumElem) { /*return TRUE for ERROR, FALSE for NO ERROR parsing the string*/

        
    int numbers=0operands=0//count numbers and operands inside the command line
        
    int i;
        
    int strSize;
        
    BOOL checkNext TRUE//a TRUE or FALSE statement to tell the program whether it is dealing with a new information

        
    strSize strlen(str);

        if (((
    str[strSize-2]) >= 48) && (str[strSize-2]) <= 57/*last character must be operand*/
            
    return TRUE;

        for (
    i=0i<strSizei++) {

            if ((
    str[i]>=48) && (str[i]<=57)) {
                if(
    checkNext == TRUEnumbers++;
                
    checkNext FALSE;
            }

            else if((
    str[i] == 37) ||(str[i] == 42) ||(str[i] == 43) ||(str[i] == 45) ||(str[i] == 47)||(tolower(str[i]) == 101)) {
                if((
    checkNext == FALSE) || (numbers<2)) /*operand must be amidst Spaces and after second number*/
                    
    return TRUE;
                
    operands++;
                
    checkNext FALSE;
            }

            else if(
    str[i]==32)
                
    checkNext TRUE;

            else if(
    str[i]!= '\n')  /*Check whether there are characters others than Numbers and operands*/
                
    return TRUE;

        }

        *
    numElem = (operands+numbers);

        if (
    operands != (numbers-1))
            return 
    TRUE;

        else
            return 
    FALSE;

    }

    /* Build a matrix containing the numbers and operands
        it works as following:
            first line of the matrix contains raw data
            second line tells the program whether the data above in the same column is a number or an operand or an empty space*/
    float** buildCommandMatrix(charcommint size){

        
    float** opMatrix//is the matrix to be operated
        
    int i0//will be used to analyze the command string
        
    BOOL checkNext=1;

        
    opMatrix allocmat(2size);

        for (
    i=0i<strlen(comm); i++) {

            if ((
    comm[i]>=48) && (comm[i]<=57)) {
                if(
    checkNext == TRUE) {
                    
    opMatrix[0][j] = (comm[i]-48);
                    
    opMatrix[1][j] = 1;
                    
    checkNext FALSE;
                }

                else {
                    
    opMatrix[0][j] *= 10.;
                    
    opMatrix[0][j] += (comm[i]-48);
                }
            }

            else if(
    comm[i]==32) {
                
    j++;
                
    checkNext TRUE;
            }
            else {
                switch(
    tolower(comm[i])) {
                    case 
    37:    opMatrix[0][j] = 6//module
                                
    opMatrix[1][j] = 2;
                                break;
                    case 
    42:    opMatrix[0][j] = 3//multiply
                                
    opMatrix[1][j] = 2;
                                break;
                    case 
    43:    opMatrix[0][j] = 1//add
                                
    opMatrix[1][j] = 2;
                                break;
                    case 
    45:    opMatrix[0][j] = 2//subtract
                                
    opMatrix[1][j] = 2;
                                break;
                    case 
    47:    opMatrix[0][j] = 4//divide
                                
    opMatrix[1][j] = 2;
                                break;
                    case 
    101:    opMatrix[0][j] = 5//exponential
                                
    opMatrix[1][j] = 2;
                                break;
                }
            }
        }
        return 
    opMatrix;
    }

    /*reads the matrix and proceeds to operate following the aforementioned pattern*/
    float operateMatrix(float** opMatint sizeBOOLdivisionErrorCheck) {

        
    int i=0j//used to analyse data and type inside the matrix. i always stores operand position.
        
    int countNum//count always 2 numbers to be operated per operation.
        
    int opNum1_positionopNum2_position//stores the numbers positions inside the matrix to be later operated.

        
    *divisionErrorCheck FALSE;
        do {

            for (; 
    i<sizei++) {
                if(
    opMat[1][i] == 2){
                    
    opMat[1][i] = 0;
                    break;
                }
            }

            
    countNum 0;

            for(
    j=(i-1); j>=0j--){

                if (
    opMat[1][j] == 1) {
                    if(
    countNum == 0) {
                        
    opNum2_position j;
                        
    countNum++;
                        
    opMat[1][j] = 0;
                    }
                    else {
                        
    opNum1_position j;
                        break;
                    }
                }

            }
            switch((int)
    opMat[0][i]) {
                case 
    1:    opMat[0][opNum1_position] += opMat[0][opNum2_position];
                        break;
                case 
    2:    opMat[0][opNum1_position] -= opMat[0][opNum2_position];
                        break;
                case 
    3:    opMat[0][opNum1_position] *= opMat[0][opNum2_position];
                        break;
                case 
    4:    if (opMat[0][opNum2_position]!=0)
                            
    opMat[0][opNum1_position] /= opMat[0][opNum2_position];
                        else
                            *
    divisionErrorCheck TRUE;
                        break;
                case 
    5:    opMat[0][opNum1_position] = pow(opMat[0][opNum1_position], opMat[0][opNum2_position]);
                        break;
                case 
    6:    opMat[0][opNum1_position] = (int)opMat[0][opNum1_position]%(int)opMat[0][opNum2_position];
                        break;
            }

            if(*
    divisionErrorCheck == TRUE)
                break;

        } while (
    opMat[1][(size-1)]!=0);

        return 
    opMat[0][0];

    }

    /*Main 'bridge' function, will solve everything outside the main function*/
    void Solve(FILEpInputFILEpOutput) {

        
    charcommand;
        
    int elements//used to allocate the command matrix

        //counters to result and errors
        
    float result;
        
    int errorCount=0;

        
    float sum=0;
        
    BOOL error//TRUE or FALSE statement to tell the program if it is dealing with a false command string

        
    float** commandMatrix;

        do{
            
    command buildCommandLine(pInput);
            if(
    strcmp(command"end\n")) {
                
    error parseCommand(command, &elements);

                if ((
    error == TRUE)&&(elements == 0))
                    
    fputs("nul\n"pOutput);

                else if (
    error == TRUE) {
                    
    errorCount++;
                    
    fputs("err\n"pOutput);
                }

                else {
                    
    commandMatrix buildCommandMatrix(commandelements);
                    
    result operateMatrix(commandMatrixelements, &error);

                    if (
    error == FALSE){
                        
    sum+=result;
                        
    fprintf(pOutput"%.0f\n"result);
                    }

                    else {
                        
    fprintf(pOutput"err: division by zero\n");
                        
    errorCount++;
                    }
                }
            }
            else break;
        }while (
    1);
        
    freemat(commandMatrix2);
        
    free(command);
        
    fprintf(pOutput"%.0f %d"sumerrorCount);

    house.h
    PHP Code:
    #define BOOL char
    #define TRUE 1
    #define FALSE 0

    FILEopenfile(char*, char*);

    void freemat(float**, int);

    float** allocmat(intint);

    charbuildCommandLine(FILE*);

    int parseCommand(char*, int*);

    float** buildCommandMatrix(char*, int);

    float operateMatrix(float**, intBOOL*);

    void Solve(FILE*, FILE*); 
  2. #2
  3. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2012
    Posts
    156
    Rep Power
    34
    Code:
        buffer = (char*) malloc (sizeof(char)*strlen(temp));
    Not enough space in buffer to copy all of temp: you're not counting the terminating NUL byte.

    Comments on this post

    • Lux Perpetua agrees
  4. #3
  5. I'm Baaaaaaack!
    Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    Jul 2003
    Location
    Maryland
    Posts
    5,538
    Rep Power
    244
    You say it won't _compile_, then you say it fails after n iterations. If it forms an executable then it compiled and linked, if it enters main then it loaded, therefore any errors after that point are all down to source code errors.

    These are all very important distinctions.

    My blog, The Fount of Useless Information http://sol-biotech.com/wordpress/
    Free code: http://sol-biotech.com/code/.
    Secure Programming: http://sol-biotech.com/code/SecProgFAQ.html.
    Performance Programming: http://sol-biotech.com/code/PerformanceProgramming.html.
    LinkedIn Profile: http://www.linkedin.com/in/keithoxenrider

    It is not that old programmers are any smarter or code better, it is just that they have made the same stupid mistake so many times that it is second nature to fix it.
    --Me, I just made it up

    The reasonable man adapts himself to the world; the unreasonable one persists in trying to adapt the world to himself. Therefore, all progress depends on the unreasonable man.
    --George Bernard Shaw
  6. #4
  7. Contributed User
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    Jun 2005
    Posts
    4,413
    Rep Power
    1871
    > So... I was all happy that have finished my college project at work, only to find it wouldn't compile for nothing on my Ubuntu platform.
    There's a really spiffy tool you can use on Ubuntu (and any other Linux) called valgrind.

    Eg.
    Code:
    $ gcc -g foo.c -lm
    foo.c: In function ‘operateMatrix’:
    foo.c:254:52: warning: incompatible implicit declaration of built-in function ‘pow’ [enabled by default]
    $ 
    $ valgrind ./a.out -i foo.txt -o answers.txt
    ==5788== Memcheck, a memory error detector
    ==5788== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
    ==5788== Using Valgrind-3.6.1-Debian and LibVEX; rerun with -h for copyright info
    ==5788== Command: ./a.out -i foo.txt -o answers.txt
    ==5788== 
    ==5788== Invalid write of size 1
    ==5788==    at 0x4C2979F: strcpy (mc_replace_strmem.c:311)
    ==5788==    by 0x400B11: buildCommandLine (foo.c:97)
    ==5788==    by 0x401445: Solve (foo.c:285)
    ==5788==    by 0x40165C: main (foo.c:343)
    ==5788==  Address 0x5454686 is 0 bytes after a block of size 6 alloc'd
    ==5788==    at 0x4C28F9F: malloc (vg_replace_malloc.c:236)
    ==5788==    by 0x400AE9: buildCommandLine (foo.c:95)
    ==5788==    by 0x401445: Solve (foo.c:285)
    ==5788==    by 0x40165C: main (foo.c:343)
    ==5788== 
    ==5788== Invalid read of size 1
    ==5788==    at 0x400B61: parseCommand (foo.c:114)
    ==5788==    by 0x40148C: Solve (foo.c:287)
    ==5788==    by 0x40165C: main (foo.c:343)
    ==5788==  Address 0x5454686 is 0 bytes after a block of size 6 alloc'd
    ==5788==    at 0x4C28F9F: malloc (vg_replace_malloc.c:236)
    ==5788==    by 0x400AE9: buildCommandLine (foo.c:95)
    ==5788==    by 0x401445: Solve (foo.c:285)
    ==5788==    by 0x40165C: main (foo.c:343)
    ==5788== 
    ==5788== Invalid read of size 1
    ==5788==    at 0x40101A: buildCommandMatrix (foo.c:163)
    ==5788==    by 0x401501: Solve (foo.c:298)
    ==5788==    by 0x40165C: main (foo.c:343)
    ==5788==  Address 0x5454686 is 0 bytes after a block of size 6 alloc'd
    ==5788==    at 0x4C28F9F: malloc (vg_replace_malloc.c:236)
    ==5788==    by 0x400AE9: buildCommandLine (foo.c:95)
    ==5788==    by 0x401445: Solve (foo.c:285)
    ==5788==    by 0x40165C: main (foo.c:343)
    ==5788== 
    ==5788== Invalid read of size 1
    ==5788==    at 0x401461: Solve (foo.c:286)
    ==5788==    by 0x40165C: main (foo.c:343)
    ==5788==  Address 0x5454b84 is 0 bytes after a block of size 4 alloc'd
    ==5788==    at 0x4C28F9F: malloc (vg_replace_malloc.c:236)
    ==5788==    by 0x400AE9: buildCommandLine (foo.c:95)
    ==5788==    by 0x401445: Solve (foo.c:285)
    ==5788==    by 0x40165C: main (foo.c:343)
    ==5788== 
    ==5788== 
    ==5788== HEAP SUMMARY:
    ==5788==     in use at exit: 52 bytes in 5 blocks
    ==5788==   total heap usage: 14 allocs, 9 frees, 2,000 bytes allocated
    ==5788== 
    ==5788== LEAK SUMMARY:
    ==5788==    definitely lost: 28 bytes in 3 blocks
    ==5788==    indirectly lost: 24 bytes in 2 blocks
    ==5788==      possibly lost: 0 bytes in 0 blocks
    ==5788==    still reachable: 0 bytes in 0 blocks
    ==5788==         suppressed: 0 bytes in 0 blocks
    ==5788== Rerun with --leak-check=full to see details of leaked memory
    ==5788== 
    ==5788== For counts of detected and suppressed errors, rerun with: -v
    ==5788== ERROR SUMMARY: 20 errors from 4 contexts (suppressed: 4 from 4)
    $ cat foo.txt
    2 3 +
    4 5 *
    end
    $ cat answers.txt 
    5
    20
    25 0$
    Do you see those "Invalid write of size 1" messages?
    That's exactly what bdb said.

    It gives you two stack traces
    - where the memory is being overrun
    - where the memory was allocated
    So you can decide to fix the amount that is being copied, or fix the amount of space needed in the first place.

    > ==5788== definitely lost: 28 bytes in 3 blocks
    And you're leaking some memory as well.
    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
  8. #5
  9. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2012
    Posts
    3
    Rep Power
    0
    You say it won't _compile_, then you say it fails after n iterations. If it forms an executable then it compiled and linked, if it enters main then it loaded, therefore any errors after that point are all down to source code errors.

    These are all very important distinctions.
    yeah, I spent hours looking for the damn error, and was so tired i mistyped stuff.

    sorry, it compiles with no build messages, but wouldn't run.

    I added 1 to the amount of memory being allocated and that solved the problem. Now I am gonna look for where the memory is leaking. Any ideas where to start?
  10. #6
  11. Contributed User
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    Jun 2005
    Posts
    4,413
    Rep Power
    1871
    > Now I am gonna look for where the memory is leaking. Any ideas where to start?
    Get valgrind installed, and do what it says here:

    > ==5788== Rerun with --leak-check=full to see details of leaked memory
    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
  12. #7
  13. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2012
    Posts
    3
    Rep Power
    0
    alright, the code is now fully functional! thanks!

IMN logo majestic logo threadwatch logo seochat tools logo