Kuro-dev
Kuro-dev

Reputation: 45

struct as return value not compiling/running

I am currently learning C and this is also my first question here. The problem is as follows. I get this warning when I try to compile this code

#include <stdio.h>
#include "LicenseManager.h"

int main(void)
{
    puts("program start");
    struct License *license = read();
    // other code
}

The read() Method is in LicenseManager.h declared as struct License *read(void){...} and the pointer it returns is a reference to static struct License license;, but when I try to compile the compiler refuses and says

warning: implicit declaration of function 'read' [-Wimplicit-function-declaration]
struct License *license = read();

Even my IDE says that the read(); method returns an int (when i look at it in the main method, in the actual LicenseManager.h it the IDE correctly says struct License *.

What I tried: I tried making a Method prototype struct License *read(void); above the main method

#include <stdio.h>
#include "LicenseManager.h"

struct License read();

int main(void)
{
    puts("program start");
    struct License *license = read();
    // other code
}

, which resolved that error and got the code to compile, however now I instantly get a

Segmentation Fault

(even before puts("program start"); is invoked).

I tried to change the returnvalue of read() from a pointer to an actual struct, however that raised the same problems.

Next I tried to change the read() method to void read(struct License *license) and give the pointer to the object externally but I still receive the same Segementation Fault every time. before the first line of code is even invoked.

after everything I tried my final code now looks like this:

#include <stdio.h>
#include "LicenseManager.h"

void read(struct License *license);

int main(void)
{
    puts("program start");
    struct License license;
    read(&license);
}

Needless to say. it still does not run. :( what do I do wrong?


So I found out some stuff, thanks to you guys and through some testing. When I use my MingW64 (i am running on windows) console I get Segmentation fault. I wanted to avoid posting large amounts of code here. but I guess I will do it. The Library i am using is an Open source Json lib called cJSON

. LicenseManager.c

#include <stdio.h>
#include "cJSON.c"
#include "cJSON.h"
#include "LicenseManager.h"
#include <time.h>

#define JSON_FILE "license.json"
void interpret(cJSON *json, struct License *license);

// DEFINE VALUES IN JSON FILE
const char *LICENSE_NAME = "printerLicense";
const char *LICENSE_COMPANY_NAME = "name";
const char *LICENSE_PRINTER_ID = "id";
const char *LICENSE_VALID_START = "validFrom";
const char *LICENSE_VALID_END = "validTo";
const char *LICENSE_PERMISSIONS = "permissions";
const char *LICENSE_HARDWARE_ID = "hardwareId";
//############################

char *readFile(void)
{
    FILE *f = fopen(JSON_FILE, "rb");
    fseek(f, 0, SEEK_END);
    long fsize = ftell(f);
    rewind(f);
    char *string = malloc(fsize + 1);
    fread(string, 1, fsize, f);
    fclose(f);
    string[fsize] = 0;
    return string;
}

void parseDate(cJSON *json, struct Date *date)
{
    fflush(stdout);
    unsigned short valYear, valMonth, valDay;
    cJSON *child = json;
    valYear = child->valueint;
    child = child->next;
    valMonth = child->valueint;
    child = child->next;
    valDay = child->valueint;
    date->year = &valYear;
    date->month = &valMonth;
    date->day = &valDay;
}

void setLicenseRights(cJSON *json, struct License *license)
{
    cJSON *rights = get_Array_item(json, LICENSE_PERMISSIONS, cJSON_False);
    int size = cJSON_GetArraySize(rights);
    char *permissions[size];
    for (size_t i = 0; i < size; i++)
    {
        permissions[i] = get_array_item(rights, i);
    }
    memcpy(license->permissions, permissions, sizeof(permissions));
}

void interpret(cJSON *json, struct License *license)
{
    cJSON *licenseJson = json->child;
    struct Date validFrom;
    parseDate(get_object_item(licenseJson, LICENSE_VALID_START, cJSON_False), &validFrom);
    struct Date validTo;
    parseDate(get_object_item(licenseJson, LICENSE_VALID_END, cJSON_False), &validTo);
    cJSON *companyName = get_object_item(licenseJson, LICENSE_COMPANY_NAME, cJSON_False);
    cJSON *hardwareID = get_object_item(licenseJson, LICENSE_HARDWARE_ID, cJSON_False);
    cJSON *printerID = get_object_item(licenseJson, LICENSE_PRINTER_ID, cJSON_False);
    setLicenseRights(licenseJson, license);
    license->companyName = companyName->valuestring;
    license->hardwareID = hardwareID->valuestring;
    license->printerID = printerID->valuestring;
    license->validFrom = &validFrom;
    license->validTo = &validTo;
}
//reads the License file. Use this to read the License.
void read(struct License *license)
{
    printf("#####################\n");
    fflush(stdin);
    char *string = readFile();
    printf("#####################\n");
    fflush(stdin);
    cJSON *json = cJSON_Parse(string);
    printf("#####################\n");
    fflush(stdin);
    interpret(json, license);
    printf("#####################\n");
    fflush(stdin);
    cJSON_Delete(json);
    free(string);
}

LicenseManager.h

#ifndef DATE
#define DATE
struct Date
{
    unsigned int *year, *month, *day;
};
#endif

#ifndef LICENSE
#define LICENSE
struct License
{
    char *companyName;
    char *printerID;
    char *hardwareID;
    struct Date *validFrom;
    struct Date *validTo;
    char *permissions[];
};
#endif

and of course main.c

#include <stdio.h>
#include "LicenseManager.h"

void read(struct License *license);

int main(void)
{
    puts("program start");
    fflush(stdout);
    struct License license;
    read(&license);
}

I forgot to include the actual LicenseManager.c file in my main. now I get some other compiler errors which i am likely to be able to fix. So the compiler just assumed that the read method just returns an int, because there was no actual declaration of it. now I just have to deal with some incompatible pointers haha.

Upvotes: 1

Views: 103

Answers (2)

ryyker
ryyker

Reputation: 23236

The warning:

warning: implicit declaration of function 'read' [-Wimplicit-function-declaration] struct License *license = read();

Is telling you that the explicit prototype provided does not match the prototype you tried to use:

struct License read();

Also, if this prototype is provided in the header file, it should not be re-declared in your source code.

Simply stated, the prototype of the function read needs to match its intended usage in the shown code:

Here is an adapted version of your code (with some additions to assist building on my system, i.e. a fake struct.)

// implementation of sample struct to allow build without "LicenseManager.h"
struct License 
{
    int a;
    int b;
    char account[80];
};

//again, because I do not have "LicenseManager.h", prototype provided here.
struct License *read(void);//corrected prototype

int main(void)
{
    puts("program start");
    struct License *license = read();//this usage dictates prototype needs of read()
    printf("%d\n%d\n%s", license->a, license->b, license->account);
    free(license);//free memory once no longer needed.
    return 0;

}

struct License *read(void)//example implementation but using proper prototype  
{
    struct License *new = malloc(sizeof(*new));//create memory
    //populate struct with some values:
    new->a = 10;
    new->b = 20;
    strcpy(new->account, "Bains");
    return new;
}
       

Upvotes: 0

arfneto
arfneto

Reputation: 1765

Please provide the header code or at least just extract read() from there and post a complete program here

A program using 3 versions for read()

Please compare the code below to your version and look at possible clues and ask about them

The program shows

Start
read() as "License read()" 35? : 35
read() as "License* read()" 9? : 9
read() as "void read(License*)" -56? : -56
End

The code

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

typedef struct { int i; } License;

License* pRead(void);
License read(void);
void readV(License* L);

int main(void)
{
    puts("Start");
    License license = read();
    printf("read() as \"License read()\" 35? : %d\n", license.i);
    License* p = pRead();
    printf("read() as \"License* read()\" 9? : %d\n", p->i);
    free(p);
    readV(&license);
    printf("read() as \"void read(License*)\" -56? : %d\n", license.i);
    puts("End");
    return 0;
};  // main()

License*    pRead()
{
    License* p = (License*)malloc(sizeof(License));
    p->i = 9;
    return p;
};

License read()
{
    License L = { 35 };
    return L;
};

void        readV(License* L) { L->i = -56; };

A small change from your code: a

    typedef struct { int i; } License;

was inserted in order to not repeat the keyword struct everywhere

Upvotes: 1

Related Questions