-2

its a very very anoing problem what i get. My problem is, gcc seems not allocate enough space to my int pointer.

Here is the code:

fns = (int*)calloc(c,sizeof(int));

So, after then i fill up this in a simple loop ones and zeros:

offset = seekToFirstParam(fnString,n);
i = 0;
while(i<c) {
    tmp[i] = readNextParam(fnString,n,offset,&s);

    if (isFunctionString(tmp[i])) {
        fns[i] = 1;
    } else {
        fns[i] = 0;
    }

    i++;
}

So this is a "flag" array, but when i debug this, and print the elements i get:

156212102, 0, 0, 0, 1, 1

Or som. like this. I don't get it, because if in the calloc method i write 1000 like this:

fns = (int*)calloc(1000,sizeof(int));

After works fine.

Ok, this is a hole function:

char **readFnParams(char *fnString, int n, int *count, int **func) {
    char **tmp;
    int  *fns = NULL;
    int c,i = 0,offset,s;

    c = getParamsCount(fnString,n);
    if (!c) {
        return NULL;
    }

    tmp = (char**)calloc(c,sizeof(char));
    fns = (int*)calloc(c,sizeof(int*));

    offset = seekToFirstParam(fnString,n); 
    while(i<c) {
        tmp[i] = readNextParam(fnString,n,offset,&s);

        if (isFunctionString(tmp[i])) {
            tmp[i]  = readNextFunctionParam(fnString,n,offset,&s);
            offset = seekToNextParam(fnString,n,offset + s - 1);
            fns[i] = 1;
        } else {
            fns[i] = 0;
            offset = seekToNextParam(fnString,n,offset);
        }

        i++;
    }
    *func = fns;
    *count = c;

    return tmp;
}

:) Ok, this is a hole .c file. Yes my previous q. end this connected, becouse its a homework.

#ifndef exccel_builder_source
#define exccel_builder_source

#include "exccel_builder.h"
#include "exccel_utils.h"
#include "exccel_function.h"

#include<stdlib.h>
#include<stdio.h>
#include<string.h>

table* _processing;

//A végére fűzi az új elemeket
void addProcess(cell_process **LIST, cell_process *new) {
    if (*LIST == NULL) {
        new->next = NULL;
        *LIST = new;
        return;
    }

    new->next = *LIST;
    *LIST = new;
}

void build(table* table) {
    int col = table->matrix->col;
    int row = table->matrix->row;
    int i,j;

    table_cell *cellTemp;
    _processing = table;

    for (i = 1; i<=row; i++) {
        for (j = 1; j<=col; j++) {
            cellTemp = getCell(table,i,j);
            if (cellTemp != NULL) {
                buildCell(cellTemp);
            }
        }
    }
}

void buildCell(table_cell *cell) {
    //Begins with '='
    if (isFunction(cell)) {
        buildCellWithFunction(cell);
    }
}

void printProcesses(cell_process *LIST, int tab) {
    cell_process *tmp = NULL;
    int i = 0;
    tmp = LIST;
    while(tmp != NULL) {
        i = 0;
        while(i++<tab) printf(" ");
        printf("%s, %d, paramPos: %i\n",tmp->func->name,tmp->func->paramsCount,tmp->paramPos);
        if (tmp->childs != NULL) {
            i = 0;
            while(i++<tab + 3) printf(" ");
            printf("Childs\n");
            printProcesses(tmp->childs, tab + 3);
        }
        tmp = tmp->next;
    }
}

void buildCellWithFunction(table_cell *cell) {
    cell_process *HEAD = NULL;
    buildCellProcessList(cell,&HEAD);
    cell->cp = HEAD;

    printf("%d,%d - cella:\n",cell->row,cell->col);
    printProcesses(HEAD,0);
}

void buildCellProcessList(table_cell *cell, cell_process **HEAD) {
    char *fnString;
    int  size;

    fnString = getCellStringValue(cell, &size);
    readFn(fnString,size,1,cell,HEAD,-1);
}

int readFn(char *fnString, int n, int offset, table_cell *cell, cell_process **LIST, int paramPos) {
    char *fnName, *fnParam;
    int  fnNameLength;
    int  *fnSig;
    int  fnSigN;
    int  fnSigI;
    int  sig;
    exccel_var *vtmp;
    exccel_function *ftmp;
    cell_process *ptmp;
    char **parameters;
    int  *fnIndexes;
    int paramsCount;
    int paramI;
    int i;

    fnName = readFnName(fnString,n,offset,&fnNameLength);
    ftmp   = getExccelFunction(fnName);
    if (ftmp == NULL) {
        return 0;
    }

    ptmp = (cell_process*)malloc(sizeof(cell_process));
    ptmp->cell = cell;
    ptmp->func = ftmp;
    ptmp->paramPos = paramPos; 
    ptmp->t    = _processing;
    ptmp->childs = NULL;

    addProcess(LIST,ptmp);

    parameters = readFnParams(fnString,n,&paramsCount,&fnIndexes);



    allocParams(ptmp->func,paramsCount);

    paramI     = 0;

    fnSig  = ftmp->signature;
    fnSigN = fnSig[0];
    fnSigI = 1;

    while(fnSigI <= fnSigN) {
        sig = fnSig[fnSigI];
        if (sig == FN_SIG_RANGE) {

            fnParam = parameters[paramI];
            vtmp    = createExccelRangeVarFromString(fnParam);
            //addParamToFunction(ftmp,vtmp);
            addParamToFunctionAtPosition(ftmp,vtmp,paramI);
            paramI++;

        } else if (sig == FN_SIG_LITERAL) {

            fnParam = parameters[paramI];
            if (fnIndexes[paramI] == 1) {
                readFn(fnParam,strlen(fnParam),0,cell,&((*LIST)->childs),paramI);
            } else {
                vtmp = createExccelVarFromString(fnParam);
                //addParamToFunction(ftmp,vtmp);
                addParamToFunctionAtPosition(ftmp,vtmp,paramI);
            }
            paramI++;

        } else if (sig == FN_SIG_LIST) {

            while(paramI<paramsCount) {
                fnParam = parameters[paramI];
                if (fnIndexes[paramI] == 1) {
                    readFn(fnParam,strlen(fnParam),0,cell,&((*LIST)->childs),paramI);
                } else {
                    vtmp = createExccelVarFromString(fnParam);
                    //addParamToFunction(ftmp,vtmp);
                    addParamToFunctionAtPosition(ftmp,vtmp,paramI);
                }
                paramI++;
            }

        } else {
            printf("Invalid signature %d\n",sig);
            exit(1);
        }

        fnSigI++;
    }

    return 1;
}

char *readFnName(char *fnString, int n, int offset, int *size) {
    char *fnName;
    int nameBuffer, i, j;

    i = offset;
    j = 0;

    nameBuffer = 8;
    fnName = (char *)calloc(nameBuffer,sizeof(char));    
    while(*(fnString + i) != '(' && i<n) {
        *(fnName + j++) = *(fnString + i++);
        if (j>=nameBuffer) {
            nameBuffer += 8;
            fnName = (char *)realloc(fnName, nameBuffer);
        }
    }

    *(fnName + j++) = '\0';
    *size = j;

    return fnName;
}

char **readFnParams(char *fnString, int n, int *count, int **func) {
    char **tmp;
    int  *fns = NULL;
    int c,i = 0,offset,s;

    c = getParamsCount(fnString,n);
    if (!c) {
        return NULL;
    }

    tmp = (char**)calloc(c,sizeof(char));
    fns = (int*)calloc(c,sizeof(*fns));

    offset = seekToFirstParam(fnString,n); 
    while(i<c) {
        tmp[i] = readNextParam(fnString,n,offset,&s);

        if (isFunctionString(tmp[i])) {
            tmp[i]  = readNextFunctionParam(fnString,n,offset,&s);
            offset = seekToNextParam(fnString,n,offset + s - 1);
            fns[i] = 1;
        } else {
            fns[i] = 0;
            offset = seekToNextParam(fnString,n,offset);
        }

        i++;
    }
    *func = fns;
    *count = c;

    return tmp;
}

int getParamsCount(char *fnString, int n) {
    int i = 0, c = 0, jump = 0;
    while(i<n) {

        if (fnString[i] == '(') {
            jump++;
        } else if (fnString[i] == ',') {
            if (jump == 1) c++;
        } else if (fnString[i] == ')') {
            jump--;
        }

        i++;
    }

    if (c > 0) {
        return c + 1;
    } else {
        return 1;
    }
}

int seekToFirstParam(char *fnString, int n) {
    int i = 0;
    while(fnString[i++] != '(' && i<n);

    return i;
}

int seekToNextParam(char *fnString, int n, int offset) {
    int i = offset;

    while(fnString[i++] != ',' && i<n);

    return i;
}

char *readNextParam(char *fnString, int n, int offset, int *size) {
    char *params, c;
    int paramBuffer, i, j;

    i = offset;
    j = 0;
    paramBuffer = 8;
    params = (char*)calloc(paramBuffer,sizeof(char));

    while((c = fnString[i++]) != ',' && c != ')' && c != '(' && i<n) {
        params[j++] = c;
        if (j >= paramBuffer) {
            paramBuffer += 8;
            params = (char*)realloc(params,paramBuffer);
        }
    }

    params[j] = '\0';
    *size = j;

    return params;
}

//Megfelelő számú nyitó ( - hez kell hogy legyen ugyanannyi )
char *readNextFunctionParam(char *fnString, int n, int offset, int *size) {
    char *fn, c;
    int  fnBf, i, j, fnStarted = 0, fnClosed = 0;

    i    = offset;
    j    = 0;
    fnBf = 8;

    fn = (char*)calloc(fnBf, sizeof(char));
    while((fnStarted != fnClosed || fnStarted == 0) && i<n) {
        c = *(fnString + i++);

        if (c == '(')
            fnStarted++;
        else if (c == ')')
            fnClosed++;

        *(fn + j++) = c;
        if (j >= fnBf) {
            fnBf += 8;
            fn = (char*)realloc(fn, sizeof(char) * fnBf);
        }

    }
    //*(fn + j++) = ')';
    *(fn + j++) = '\0';
    *size = j;

    return fn;
}

#endif

And input like this: =SZORZAT(MDETERM(A1:D4),NAGY(A1:D4,0),10,20,30)

DevMetal91
  • 340
  • 3
  • 13
  • 6
    A minimal compilable example that reproduces the problem would be useful. – Tom Fenech May 15 '14 at 18:14
  • 1
    I hazard to guess your `readNextParam(fnString,n,offset,&s);` is walking on your allocation of `fns`. Either that or the `tmp[i]` assignment. Either way, post **all** of the code required to reproduce the problem. Pretend we don't have all the code you're privy to, then stop pretending, because we *don't*. Finally, sample data required to reproduce along with the code. – WhozCraig May 15 '14 at 18:16
  • From what we can see here, the first `calloc` call seems correct. Concur with @WhozCraig that heap overflow (due to undersized `tmp` or `s`) is probably the real issue. – nobody May 15 '14 at 18:17
  • @JonathanLeffler i tried, but not working. I can not add compilable example, becouse its a big program little function. – DevMetal91 May 15 '14 at 18:18
  • @WhozCraig: And if the sample data can be incorporated into the program itself, that would be even better (e.g. modify it to read data from an array rather than by calling `readNextParam`, which I presume is an input function). – Keith Thompson May 15 '14 at 18:19
  • ouch. Be sure to allocate space for the type you actually want to save, not some (maybe-related) other one. Try this idiom: `pointer = malloc(count*sizeof*pointer);`. – Deduplicator May 15 '14 at 18:20
  • Post your code for the functions `seekToFirstParam`, `readNextParam`, `readNextFunctionParam`, and `isFunctionString`. And again, a sample string that exhibits the problem as input data. – WhozCraig May 15 '14 at 18:21
  • 2
    This is not very dissimilar to your previous question http://stackoverflow.com/questions/23598235/c-malloc-in-function-throw-memory-error - the same exact advice applies. – nobody May 15 '14 at 18:22

1 Answers1

2

It looks to me like you aren't allocating correctly, you have:

tmp = (char**)calloc(c,sizeof(char));

The first line, tmp, is allocating c elements of size char (c elements of 1 byte), I think you want c elements of size char * (c elements of size 4 or 8 bytes per element depending on if you are 32 or 64 bit platform). Since your routine readNextParam() is returning char * to store in this array, you need to change the calloc sizeof for tmp to:

tmp = calloc(c,sizeof(char*));

Because of this, I believe you have memory overwrites when you write into the tmp array that bleed into your other array. By making both "1000" elements, you've padded out that first calloc far enough that the overwrites are still in that same piece of memory.

JohnH
  • 2,713
  • 12
  • 21
  • 1
    shouldn't it also be : fns = (int*)calloc(c,sizeof(int)); – Jiminion May 15 '14 at 18:42
  • 2
    As far as that goes, *neither* of them should have casts. This is, after all, C. And @Jim, the latter is ok. `sizeof(*fns)` will reduce at compile-time, not runtime, to the correct size. That line is ok. – WhozCraig May 15 '14 at 18:44
  • Won't the compiler deal with the (harmless) cast as well? At least the cast isn't obfuscating (and wrong), so I'm not sure why leaving the sizeof inaccuracy in place is 'OK' even though the compiler can handle it. – Jiminion May 15 '14 at 19:42
  • 1
    @Jim -- yes, if on a 64bit platform, that line is probably overallocating that array by a factor of 2, as `int` is usually a 32bit value even on 64 bit boxes. If on a 32 bit machine, then it works out, not because the code is right, but because of luck. – JohnH May 15 '14 at 20:20