Search code examples
cdynamic-memory-allocationrealloc

Problem when trying to allocate memory in C


I'm having a problem when using realloc() in one function and with the same algorithm, it doesn't work for the other. I can't understand where I'm making a mistake.

For the initVertex function this algorithm works fine. But in the initFace every time I try to allocate memory for the faces it says:

realloc(): invalid next size.

The files I'm reading from is in .obj format:

for vertex: v -0.187264 0.10108 0.266814

for face: f 938/938/936 944/944/942 936/936/934

Here is the code:

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

#include "Scene.h"

#define MAX_ID 10
#define LIMIT 10
#define MEM_INCREASE 10


void setArrToZero(char *arr) {
    for (int i = 0; i < LIMIT; ++i) {
        *(arr + i) = 0;
    }
}

void initFace(Object *obj, char *line, int length, int *maxFaces) {
    int i = 0, strCounter = 0;
    (obj->faces)[obj->numberOfFaces].size = 0;
    (obj->faces)[obj->numberOfFaces].vertex = (int*) malloc(MAX_ID * sizeof(int));
    char *numStr = (char*) malloc(length * sizeof(char));
    enum boolean flag = FALSE;
    if (obj->numberOfFaces == *maxFaces) {
        obj->faces = (Face*) realloc(obj->faces,
                (*maxFaces + MEM_INCREASE) * sizeof(Face));
        *maxFaces += 10;
    }
    while (i != length) {
        char c = line[i];
        if (c == ' ' && flag == FALSE)    //turn the flag on
            flag = TRUE;
        if (c == '/' && flag == TRUE) { //turn the flag off and initialize Face.
            flag = FALSE;
            (obj->faces)[obj->numberOfFaces].vertex[obj->faces->size] = atoi(
                    numStr);
            (obj->faces)[obj->numberOfFaces].size++; // increase number of vertexes of the face.
            setArrToZero(numStr);
            strCounter = 0;
        }
        if (flag == TRUE) {
            numStr[strCounter] = c;
            strCounter++;
        }
        if ((obj->faces)[obj->numberOfFaces].size == MAX_ID) {
            break;
        }

        i++;
    }
    obj->numberOfFaces++;
    free(numStr);
}

void initVertex(Object *obj, char *line, int *maxVertexes) {
    float x, y, z;
    if (line[1] != ' ')
        return;
    else {
        if (obj->numberOfVertexes == *maxVertexes) {
            obj->vertexes = (Vertex*) realloc(obj->vertexes,
                    sizeof(Vertex) * (*maxVertexes + MEM_INCREASE));
            *maxVertexes += 10;
        }
        sscanf(line, "%*[^-0123456789]%f%*[^-0123456789]%f%*[^-0123456789]%f",
                &x, &y, &z);
        (obj->vertexes)[obj->numberOfVertexes].x = x;
        (obj->vertexes)[obj->numberOfVertexes].y = y;
        (obj->vertexes)[obj->numberOfVertexes].z = z;
        obj->numberOfVertexes++;
    }
}

Object* createObject(char *fileName) {
    Object *obj = (Object*) malloc(sizeof(Object));
    int maxVertexes = 10, maxFaces = 10;
    obj->numberOfFaces = 0;
    obj->numberOfVertexes = 0;
    obj->vertexes = (Vertex*) malloc(maxVertexes * sizeof(Vertex));
    obj->faces = (Face*) malloc(maxFaces * sizeof(Face));
    FILE *inputF;
    size_t len = 0;
    char *line = NULL;
    inputF = fopen(fileName, "r");
    if (inputF == NULL) {
        printf("File not exist!");
        return NULL;
    }
    while (!feof(inputF)) {
        getline(&line, &len, inputF);
        char c = line[0];
        switch (c) {
        case 'v':
            initVertex(obj, line, &maxVertexes);
            break;
        case 'f':
            initFace(obj, line, len, &maxFaces);
            break;
        default:
            break;
        }
    }
    return obj;
}

int main() {


    Object *obj = createObject("Donald.obj");
    printf("done");

}

Solution

  • initVertex() reallocates the array vertexes before it uses the out-of-bound index numberOfVertexes.

    initFace() uses the out-of-bound index numberOfFaces twice here:

        (obj->faces)[obj->numberOfFaces].size = 0;
        (obj->faces)[obj->numberOfFaces].vertex = (int*) malloc(MAX_ID * sizeof(int));
    

    and only after having done reallocates the array faces.

    Accessing the array faces out of bound provokes undefined behaviour. Anything can happen from then one. In this particular case the program's memory management seems to have been messed up.