0

I'm stuck with memory allocation for a couple of hours now. Basically, I have to add a new Graphic Element to the Vector Graphic for which initialization of VectorGraphic is necessary.

First problem is with memory allocation inside the InitVectorGraphic method which is fixed? (I think) Now the second problem I'm stuck with is that even though memory is allocated from InitVectorGraphic method, pElements has no memory inside the AddGraphicElement method. (i.e, even after initializing it in one method (InitVectorGraphic method), changes won't reflect in other methods)

Here is my full code:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>

enum{ 
    RUNNING = 1 
}; 

struct Point        
{
    int x, y; 
}; 

struct Line        
{ 
    Point start; 
    Point end; 
}; 

struct GraphicElement     
{ 
    enum{ 
        SIZE = 256 
    }; 
    unsigned int numLines;
    Line* pLines; 
    char name[SIZE]; 
}; 

typedef struct         
{ 
    unsigned int numGraphicElements; 
    GraphicElement* pElements; 
}VectorGraphic; 

void InitVectorGraphic(VectorGraphic* image){
    image = (VectorGraphic*)malloc(sizeof(VectorGraphic));
    (*image).pElements = (GraphicElement*)malloc(sizeof(GraphicElement)* 256);
//Problem part 1
    };

void AddGraphicElement(VectorGraphic* image){
    printf("\nADDING A Graphic Element"); //Problem part 2
    int index = (*image).numGraphicElements;

    printf("\nPlease enter the name of the new GraphicElement(<256 characters): ");
    scanf("%s", &(*image).pElements[index].name);
    printf("How many lines are there in the  new GraphicElement? ");
    scanf("%d", &(*image).pElements[index].numLines);
    (*image).pElements[index].pLines = (Line*)malloc(sizeof(Line)* (*image).pElements[index].numLines);
    for (int i = 0; i < (*image).pElements[index].numLines; i++){
        Line line;
        printf("Please enter the x coord of the start point of line index %d: ", i);
        scanf("%d", &line.start.x);
        printf("Please enter the y coord of the start point of line index  %d: ", i);
        scanf("%d", &line.start.y);
        printf("Please enter the x coord of the end point of line index %d: ", i);
        scanf("%d", &line.end.x);
        printf("Please enter the y coord of the end point of line index %d: ", i);
        scanf("%d", &line.end.y);

        (*image).pElements[index].pLines[i] = line;
    }

    (*image).numGraphicElements = (*image).numGraphicElements + 1;
    printf("Added");
    //add graphicElement to Image

};
void ReportVectorGraphic(VectorGraphic* image){
    printf("\nVectorGraphic Report");
    for (int i = 0; i < (*image).numGraphicElements; i++){
        printf("\nReporting Graphic Element #%d", i);
        printf("\nGraphic Element name: %s", (*image).pElements[i].name);
        for (int j = 0; j < (*image).pElements[i].numLines; j++){
            printf("\nLine #%d start x: %d", j, (*image).pElements[i].pLines[j].start.x);
            printf("\nLine #%d start y: %d", j, (*image).pElements[i].pLines[j].start.y);
            printf("\nLine #%d end x: %d", j, (*image).pElements[i].pLines[j].end.x);
            printf("\nLine #%d end y: %d", j, (*image).pElements[i].pLines[j].end.y);
        }       
    }

};

void CleanUpVectorGraphic(VectorGraphic* image){
    free(image);
};

VectorGraphic Image; 


int main()        
{ 
    char response; 
    InitVectorGraphic(&Image); 
    while (RUNNING)               
    { 
        printf("\nPlease select an option:\n");
        printf("1. Add a Graphic Element\n"); 
        printf("2. List the Graphic Elements\n"); 
        printf("q. Quit\n"); printf("CHOICE: ");
        fflush(stdin); 
        scanf("%c", &response); 
        switch (response)                      
        { 
        case '1':AddGraphicElement(&Image); 
            break; 
        case '2':ReportVectorGraphic(&Image);
            break; 
        case 'q':CleanUpVectorGraphic(&Image); 
            return 0;
        default:printf("Please enter a valid option\n"); 
        }
        printf("\n"); 
    } 
}

What is the solution?

too honest for this site
  • 12,050
  • 4
  • 30
  • 52
Ravi Kiran
  • 565
  • 1
  • 8
  • 22
  • 2
    Is this c or c++? – Captain Giraffe Sep 25 '16 at 22:06
  • When I define `void f(int x) {x = 5;}` and then do `int i = 7; f(i);` what is the value of i afterwards? What about if I do `f(7);` - what is the value of 7 afterwards? And finally, if I define `void g(int *q) {q = malloc(sizeof(int));}` and do `int *p = NULL; g(p);` what is the value of p afterwards? – user253751 Sep 25 '16 at 22:07
  • I'm sorry, this is in C. @CaptainGiraffe – Ravi Kiran Sep 25 '16 at 22:09
  • Have you worked through with a debugger? First look shows various problems, such as with `scanf` and not realising that a function takes a *copy* of the variable you supply and then forgets it on return. In `InitVectorGraphic` you immediately overwrite the pointer argument supplied and after its return there will be a memory leak. – Weather Vane Sep 25 '16 at 22:10
  • 1
    1) Don't spam language tags! 2) C does not support _methods_, only _functions_. 3) Don't cast the result of `malloc` & friends in C. – too honest for this site Sep 25 '16 at 22:12
  • 1
    `fflush(stdin)` is not defined by the C language - remove it, or update your tags to indicate which language you are really using. – mlp Sep 25 '16 at 22:16
  • `#include` is not defined by the C language - remove it, or update your tags to indicate which language you are really using. – mlp Sep 25 '16 at 22:18
  • 1
    Read about "pass by value". It's always a mistake to take a function parameter and then overwrite the old value of the parameter on the first line of the function. – M.M Sep 25 '16 at 22:26
  • My answer to [C Programming: malloc() inside another function](http://stackoverflow.com/a/2838207/179715) might be of interest to you. – jamesdlin Sep 25 '16 at 23:51

1 Answers1

0

This is very standard confusion with pointers. You need following changes:

VectorGraphic* Image; //make it a pointer
void InitVectorGraphic(VectorGraphic** image) //expect pointer-to-pointer
{
    *image = (VectorGraphic*)malloc(sizeof(VectorGraphic)); //assign allocated buffer to pointer
    (*image)->pElements = (GraphicElement*)malloc(sizeof(GraphicElement)* 256);
}

InitVectorGraphic(&Image); //call remains the same

In your old code, you are leaking memory, you can think of image as local defined variable as below:

InitVectorGraphic(VectorGraphic* image)
{
  image = malloc(); //Here you are allocating memory to a local variable not to the address Image
  //no free()'ing of image variable
}

Steps of execution as per your old code are simply making two assignment with second assignment overwriting original one:

VectorGraphic *image = &Image;
image = malloc();
JamesWebbTelescopeAlien
  • 3,547
  • 2
  • 30
  • 51