unexpected initialization of global variable - c

I have the header file as:
test.h
//Mandatory fields size macro
#define size_uid 65
#define size_txn 33
#define size_adhaarNo 13
#define size_ver 4
#define size_input 65
#define size_photo 1024*1024*10
#define size_pseudonym 50
#define size_name 50
//Mandatory fields declaration
char uid[size_uid];
char txn[size_txn];
char adhaarNo[size_adhaarNo];
char ver [size_ver];
char *photo;
char pseudonym[size_pseudonym];
char name[size_name];
char input[size_input];
void incorrect_val_test(FILE *, FILE *, FILE *, FILE *, FILE *, FILE *,FILE *,FILE *,FILE *,FILE*);
test.c
#include "test.h"
//Mandatory fields declaration
char uid[] = "865A80A01C70A9E0D5FC5F4D354A9155BF58CD483B1397C92614E5BC92317ACC";
char txn[] = "23da7b99-c561-4102-9df8-d37fbfe1";
char adhaarNo[] = "250241800087";
char ver [] = "1.0";
char *photo = (char *)malloc(sizeof(char)*size_photo);
char pseudonym[] = "2b6c55566d14459991513fb00bce34ed";
char name[] = "Amarjeet Sharma";
char input[] = "936a185caaa266bb9cbe981e9e05cb78cd732b0b3280eb944412bb6f8f8f07af";
void incorrect_val_test(FILE *ver, FILE *ts, FILE *txn, FILE *vtxn, FILE *uid, FILE *input, FILE *adhaarNo, FILE *photo, FILE *name, FILE *pseudonym)
{
//Some initialization and files are opened here....
photo = (char *)malloc(sizeof(char)*size_photo);
FILE *photos = fopen("./input/data.txt","r");
if(photos == NULL)
{
printf("Can't open data file.\n");
return;
}
i=0;
while((read_char = fgetc(photos))!= EOF)
{
if(read_char == '\n')
continue;
photo[i]= read_char;
i++;
}
// Some more processing done here
}
main.c
int main()
{
// Some files are opened here to read data.
incorrect_val_test(fp_ver, fp_ts, fp_txn, fp_vtxn, fp_uid, fp_input, fp_adhaarNo, fp_photo, fp_name, fp_pseudonym);
return 0;
}
When I am compiling it gives the following error message
error message
warning: assignment from incompatible pointer type
[-Wincompatible-pointer-types] photo = (char
*)malloc(sizeof(char)*size_photo); error: incompatible types when assigning to type ‘FILE {aka struct _IO_FILE}’ from type ‘char’
photo[i]= read_char;
Can anybody point me where I am going wrong?

You can have a function call like
char *photo = (char *)malloc(sizeof(char)*size_photo);
inside a function. This is not allowed in global scope. Remove the global one, leave the one present inside the incorrect_val_test() function.
Moreover, please do not cast the return value of malloc() and family in C.
Solution:
define char *photo = NULL; in global scope.
As you've done, allocate memory to photo inside your incorrect_val_test(), like
char *photo = malloc(size_photo); //cast not required
// sizeof(char) is guranteed to be 1
Then , you've got FILE *photo in your incorrect_val_test() function in the function parameter list
void incorrect_val_test(..., FILE *photo, ...)
which shadows the global char * photo.
IMHO, what you want is to write
void incorrect_val_test(..., FILE *photos, ...)
^
|
and, inside the function body,
photos = fopen("./input/data.txt","r");
but, then, why to use variables names with a single character difference? Use something more verbose and easy to distinguish.
Note: After you're done using photo, don't forget to free() the allocated memory to avoid memory-leak.

You have the function
void incorrect_val_test(..., FILE *photo, ...)
Notice that you have an argument that shadows the global variable. That's the cause of your errors in the question.

Related

How to make Data File Handling functions in a private header file? (To be edited)

EDIT: This question is to be edited, please stop reading. Don't waste your time! Thank you
I’m doing High School Turbo C++. I tried making a header file containing a function to search a binary file.
My Headerfile program is: alpha.h
#ifndef ALPHA_H
#define ALPHA_H
#if !defined __FSTREAM_H
#include<fstream.h>
#endif
#if !defined __PROCESS_H
#include<process.h>
#endif
void searchclass(char* & buf, int, char *);
#endif
According to some research that I did on the internet, I found out that the definitions will go in a separate program not in the main header file. So this is that program: ALPHA.CPP
#include<process.h>
#include<fstream.h>
#include"alpha.h"
//All the Definations of the alpha.h header file go here
void searchclass(char* & buf, int s_var, char * file)
{
ifstream fin;
fin.open(file, ios::binary);
if(!fin)
{
cout<<"Error 404: File not found";
exit(-1);
}
while(!fin.read((char*)buf, sizeof(buf)))
if(buf.getint()==s_var)
cout<<"\n\nRecord Found!";
buf.show();
fin.close();
}
Keep in mind that I'm trying to write a function that can help me search a random binary file storing records in form of classes for some specific int variable. So it should be able to take in an object of any class and perform a search in it.
This is the program I wrote to check my header file. A_TEST.CPP
#include<iostream.h>
#include<conio.h>
#include<fstream.h>
#include"alpha.h"
#include<string.h>
class stu
{ int rn;
char name[20];
public:
void show() //Display Function
{
cout<<"\n\tStudent Details:";
cout<<"\nName: "<<name;
cout<<"\nRoll No.: "<<rn;
}
stu() //constructor
{
rn = 6;
strcpy(name,"Random Name");
}
int getint() //return function
{
return rn;
}
};
char* returnfile()
{ char file[10];
strcpy(file,"file.dat");
return file;
}
void main()
{
clrscr();
int search_var=6;
stu S1;
char file[10];
strcpy(file, "test.dat");
ofstream fout;
fout.open(file, ios::binary);
fout.write((char*)&S1, sizeof(S1));
fout.close();
searchclass((char*)& S1, search_var, file);
getch();
}
On compiling A_TEST.CPP (above program), I get the warning:
Warning A_TEST.CPP 45: Temporary used for parameter 'buf' in call to
'searchclass(char * &,int,char *)'
On linking, it gives me this error:
Linking A_TEST.EXE
Linker Error: Undefined symbol searchclass(char nearnear&,int,char
near) in module A_TEST.CPP
I don't think that the ALPHA.CPP file is getting linked with the alpha.h file, and if I compile ALPHA.CPP file it gives me the following errors:
Error ALPHA.CPP 17: Structure required on left side of . or .*
Error ALPHA.CPP 19: Structure required on left side of . or .*
Warning ALPHA.CPP 21: Parameter 's_var' is never used
In ALPHA.CPP 17 and 19, you can't write code like that, because int type hasn't getint() or show() methods. If you want to check int in the buffer, you should convert pointer into "int*" first, try below code:
int count = fin.read((char*)buf, sizeof(buf));
for (int i = 0; i<(count-4); ++i) {
if (*(int *)(buf + i) == s_var) {
cout << "\n\nRecord Found!";
break;
}
}

Strange characters from char array in structure

Here are my structures (defined in a header file):
typedef struct
{
char *name;
char *value;
} struct_param;
typedef struct
{
char *UID;
int number;
char *type;
char *name;
struct_param param[10];
} struct_cmd;
the prototype :
struct_cmd *ParseFile(char buffer[]);
The function in the c file:
struct_cmd *ParseFile(char buffer[])
{
struct_cmd *cmd;
cmd = malloc(sizeof(struct_cmd));
...
if (mxmlGetFirstChild(node_msgUID) != NULL)
cmd->UID = node_msgUID->child->value.opaque;
...
printf("Message Type :: %s | Message UID :: %s \n", cmd->type, cmd->UID);
...
return cmd;
}
The printf in ParseFile works perfectly.
Now, from the main function:
int main(int argc, char **argv)
{
...
struct_cmd *mystruct;
mystruct = malloc(sizeof(struct_cmd));
mystruct = ParseFile(buf);
printf("Message Type :: %s | Message UID :: %s \n", mystruct->type, mystruct->UID);
...
}
The same printf doesn't work. The function returns the structure, but values are weird... It's not values, but strange characters.
Any idea?
Thanks
You are making a shallow copy from the data allocated by Mini-XML to your own struct cmd.
For example, this statement copies a pointer, not the actual characters:
cmd->UID = node_msgUID->child->value.opaque;
cmd->UID still refers to the original memory block allocated by Mini-XML. There's nothing wrong with that, just remember that this memory will be de-allocated once you call mxmlDelete. Which is probably what you are doing somewhere near the end of function ParseFile. I am guessing here, since you did not post all your code.
Possible solutions:
Instead of a shallow copy, make a deep copy, e.g. with strdup: cmd->UID = strdup(node_msgUID->child->value.opaque);
Do all processing before freeing memory.
Remember, you are programming in plain C, without a garbage collector. Memory management is your responsibility.
Just to be sure... I must use malloc before setting the value to my structure in the ParseFile function, right?
So as I said in a comment, if I manually set cmd->type = "type" in the ParseFile function, it's correctly showed in the console (in the main).
But if I don't, strange characters are displayed.
I changed the declaration of my structure and added "extern", but it didn't change anything.
I'm lost...
define cmd globally instead of locally in the function:
struct_cmd *ParseFile(char buffer[])
{
struct_cmd *cmd;
cmd = malloc(sizeof(struct_cmd));
...
if (mxmlGetFirstChild(node_msgUID) != NULL)
cmd->UID = node_msgUID->child->value.opaque;
...
printf("Message Type :: %s | Message UID :: %s \n", cmd->type, cmd->UID);
...
return cmd;
}
to:
struct_cmd *cmd;
struct_cmd *ParseFile(char buffer[])
{
cmd = malloc(sizeof(struct_cmd));
...
if (mxmlGetFirstChild(node_msgUID) != NULL)
cmd->UID = node_msgUID->child->value.opaque;
...
printf("Message Type :: %s | Message UID :: %s \n", cmd->type, cmd->UID);
...
return cmd;
}

C - segmentation fault using struct member values

I'm running head-long into a segmentation fault that I'm not sure of the reason behind.
Short story... I store file names into members of a struct, then use those members to open files to load their data into linked lists. This is working fine when I only have two file, but when I go to add a third, I get a segmentation fault opening the first file.
Code will hopefully illustrate better...
int main(int argc, char* argv[])
{
/* Initalise tennisStore struct */
TennisStoreType *ts;
systemInit(ts);
/* Variables */
ts->stockFile = "stock.csv";
ts->custFile = "customer.csv";
ts->salesFile = "sales.csv";
/* Load data from files */
loadData(ts, ts->custFile, ts->stockFile);
...
}
The struct details for ts...
typedef struct tennisStore
{
CustomerNodePtr headCust;
unsigned customerCount;
StockNodePtr headStock;
unsigned stockCount;
char *custFile;
char *stockFile;
char *salesFile;
} TennisStoreType;
systemInit() seems pretty innocuous, but here's the code just in case...
void systemInit(TennisStoreType *ts)
{
/* Set ts options to be ready */
ts->headCust = NULL;
ts->headStock = NULL;
ts->customerCount = 0;
ts->stockCount = 0;
}
loadData()...
void loadData(TennisStoreType* ts, char* customerFile, char* stockFile)
{
/* Load customer data */
addCustNode(ts, customerFile);
/* Load stock data */
addStockNode(ts, stockFile);
}
Here's where the problem occurs...
void addStockNode(TennisStoreType* ts, char* stockFile)
{
/* Variables */
StockNodePtr head, new, current, previous;
unsigned stkLevel;
char *stkTok1, *stkTok2, *stkTok3, *stkTok4;
char buf[BUFSIZ];
float stkPrice;
FILE *stream;
/* Set head */
head = NULL;
/* Open stock file */
stream = fopen(stockFile, "r"); <-- segmentation fault when sales.csv line included
assert(stream);
while (fgets(buf, BUFSIZ, stream))
{
...
}
...
}
As above, when the ts->salesFile = "sales.csv" line is included in main, the segmentation fault occurs. When it isn't, all is fine (file opens, I can read from it, write to it etc). Cannot for the life of me understand why, so I'm appealing to your good nature and superior knowledge of C for potential causes of this problem.
Thanks!
ts is uninitialized, and used as is, in systemInit().
It should be malloc()ed..
change
TennisStoreType *ts;
to
TennisStoreType *ts=malloc(sizeof(TennisStoreType));
or
change
TennisStoreType *ts;
systemInit(ts);
to
TennisStoreType ts;
systemInit(&ts);
You never actually created your TennisStoreType object.
int main(int argc, char* argv[])
{
TennisStoreType *ts; // <-- allocates 4 bytes for a pointer
systemInit(ts); // <-- pass the pointer to nowhere around.
Try inserting ts = malloc(sizeof(TennisStoreType)) in between those two lines.

Compiler Error in C: expected ')' before '*' token

As the title says, keep getting this error when trying to compile. From Googling this error people have said that it is not declared in the header file but my function is static and it is not in a header file, I prototyped it.`
#include <recGbl.h>
#include <devSup.h>
#include <devLib.h>
#include <drvIpac.h>
#include <dbScan.h>
#include <epicsExport.h>
static int cardinit(cardinfo *card); // <-- line that gives the error
typedef struct cardinfo{
struct cardinfo *next;
struct io_mem_read *pMem; /* IP register (A16) mem address */
word *rambase; /* RAM conversion memory mem address*/
int isconfigured;
int doram; /* 1 if we are using the RAM to output data.
0 if we are writing to registers (AO style) */
int cardnum;
int vmeslotnum;
int ipslotnum;
/* these values mirror the hardware registers */
word csr;
word offset;
word numconv;
word clockrate;
word vectnum;
word dacval[MAXSIGNAL];
word oldispresent;
/* used to detect a reinsertion of a carrier card.
see subroutine ispresent() below. */
/* use to update process variables */
IOSCANPVT ioscanpvt;
} cardinfo;
static int Hy8402init(int vmeslot, int ipslot, int clockrate) {
cardinfo *card;
card->vmeslotnum = vmeslot;
card->ipslotnum = ipslot;
card->cardnum = 1;
card->clockrate = clockrate;
card->vectnum = 10;
cardinit(card);
return TRUE;
}
static int cardinit(cardinfo *card){
word rprobe;
int res;
volatile word *ramptr;
card->pMem= ipmBaseAddr(card->vmeslotnum,
card->ipslotnum,ipac_addrIO);
if (card->pMem==NULL){
printf("Error in %s",devstr);
printf( "%s: Cannot determine base address\n",devstr);
return FALSE;
}
res=devReadProbe(sizeof (word),(char *) card->pMem,(char *) &rprobe);
if (res!=OK){
printf("%s: NO DEVICE at %x (vmeslot %d, ipslot %d)\n",devstr,
(int)card->pMem,
card->vmeslotnum,card->ipslotnum);
return FALSE;
}
return TRUE;
}
`
cardinfo struct is still undefined on the line with error. Put a forward declaration before it:
struct cardinfo;
static int cardinit(struct cardinfo *card);
This line of code:
static int cardinit(cardinfo *card);
should be added after the definition of your cardinfo structure.
You need to put the line
static int cardinit(cardinfo *card);
after the definition of the cardinfo structure.
At that line, the compiler doesn't yet know that cardinfo is a struct. Precede it with the line struct cardinfo;
You have declared a function which has a input variable of a type which the compiler is not aware when it parses it. i.e the struct defintion follows your function declaration.
So please do a forward declaration of the structure when you want to compile such code.
In computer programming, a forward declaration is a declaration
of an identifier (denoting an entity such as a type, a variable, or a
function) for which the programmer has not yet given a complete definition.
This link has a nice article on when full declarations are not required.

Ignore "initialization from incompatible pointer type" warnings?

Is there a compiler directive in order to ignore the "initialization from incompatible pointer type" warnings in Hardware_MouseDrivers_GPM_Methods and Hardware_MouseDrivers_DevInput_Methods? Turning off warnings globally is not an option though.
#include <stdio.h>
/* Mouse driver interface */
typedef struct _Hardware_MouseDriver {
int (*open)(void*, char *);
int (*close)(void*);
int (*poll)(void*);
} Hardware_MouseDriver;
/* GPM */
typedef struct _Hardware_MouseDrivers_GPM {
char *path;
} Hardware_MouseDrivers_GPM;
static int Hardware_MouseDrivers_GPM_Open(Hardware_MouseDrivers_GPM *this, char *path);
static int Hardware_MouseDrivers_GPM_Close(Hardware_MouseDrivers_GPM *this);
static int Hardware_MouseDrivers_GPM_Poll(Hardware_MouseDrivers_GPM *this);
static int Hardware_MouseDrivers_GPM_Open(Hardware_MouseDrivers_GPM *this, char *path) {
printf("GPM: Opening %s...\n", path);
this->path = path;
}
static int Hardware_MouseDrivers_GPM_Close(Hardware_MouseDrivers_GPM *this) {
printf("GPM: Closing %s...\n", this->path);
}
static int Hardware_MouseDrivers_GPM_Poll(Hardware_MouseDrivers_GPM *this) {
printf("GPM: Polling %s...\n", this->path);
}
Hardware_MouseDriver Hardware_MouseDrivers_GPM_Methods = {
.open = Hardware_MouseDrivers_GPM_Open,
.close = Hardware_MouseDrivers_GPM_Close,
.poll = Hardware_MouseDrivers_GPM_Poll
};
/* DevInput */
typedef struct _Hardware_MouseDrivers_DevInput {
char *path;
} Hardware_MouseDrivers_DevInput;
static int Hardware_MouseDrivers_DevInput_Open(Hardware_MouseDrivers_DevInput *this, char *path);
static int Hardware_MouseDrivers_DevInput_Close(Hardware_MouseDrivers_DevInput *this);
static int Hardware_MouseDrivers_DevInput_Poll(Hardware_MouseDrivers_DevInput *this);
static int Hardware_MouseDrivers_DevInput_Open(Hardware_MouseDrivers_DevInput *this, char *path) {
printf("DevInput: Opening %s...\n", path);
this->path = path;
}
static int Hardware_MouseDrivers_DevInput_Close(Hardware_MouseDrivers_DevInput *this) {
printf("DevInput: Closing %s...\n", this->path);
}
static int Hardware_MouseDrivers_DevInput_Poll(Hardware_MouseDrivers_DevInput *this) {
printf("DevInput: Polling %s...\n", this->path);
}
Hardware_MouseDriver Hardware_MouseDrivers_DevInput_Methods = {
.open = Hardware_MouseDrivers_DevInput_Open,
.close = Hardware_MouseDrivers_DevInput_Close,
.poll = Hardware_MouseDrivers_DevInput_Poll
};
/* Test drivers */
void TestDriver(Hardware_MouseDriver driver, void *data) {
/* Access the driver using a generic interface
* (Hardware_MouseDriver) */
driver.poll(data);
}
void main() {
Hardware_MouseDrivers_GPM gpm;
Hardware_MouseDrivers_DevInput devinput;
Hardware_MouseDrivers_GPM_Open(&gpm, "/dev/gpmctl");
Hardware_MouseDrivers_DevInput_Open(&devinput, "/dev/input/mice");
TestDriver(Hardware_MouseDrivers_GPM_Methods, &gpm);
TestDriver(Hardware_MouseDrivers_DevInput_Methods, &devinput);
Hardware_MouseDrivers_GPM_Close(&gpm);
Hardware_MouseDrivers_DevInput_Close(&devinput);
}
Cast the assignments to the proper types (function pointers with void * rather than your instance pointer):
.open= (int (*)(void*, char *))Hardware_MouseDrivers_GPM_Open;
Or make a type and use it in the definition and initialization of the struct:
typedef int (*openfcnt_t)(void*, char *);
typedef struct _Hardware_MouseDriver {
openfnct_t open;
} Hardware_MouseDriver;
and then
.open= (openfnct_t)Hardware_MouseDrivers_GPM_Open;
EDIT:
Upon further thought the easiest and least fiddly way for a C program will be:
.open= (void *)Hardware_MouseDrivers_GPM_Open;
I guess the obvious answer to this is the question "why not fix the code to use the right pointer type"?
EDIT:
OK, I can understand that you don't want to complicate the code unnecessarily, but I don't think it's that much of a complication, or even an unneccessary one.
Let's look at the field open in the struct Hardware_MouseDriver, which is supposed to be a pointer to a function that takes a pointer to void as its first argument.
To initialize this field, you use a pointer to the function Hardware_MouseDrivers_GPM_Open, and at another place a pointer to the function Hardware_MouseDrivers_DevInput_Open. None of these take a pointer to void as their first argument, and this is of course what the compiler warns about.
Now, if a void pointer is the same size as these pointers, and there are no other surprising differences between how they are stored and handled, calls to these functions through the open pointer will work as expected. It is likely that it will, and I guess that with this type of low-level code it is unlikely that someone will port it to TOPS-20 or something. But there is no guarantee that it
will work, and it looks (to me) strange. (And to the compiler, obviously!)
So my suggestion would be to change code like this:
static int Hardware_MouseDrivers_GPM_Open(Hardware_MouseDrivers_GPM *this, char *path) {
printf("GPM: Opening %s...\n", path);
this->path = path;
}
to the just slightly more complicated:
static int Hardware_MouseDrivers_GPM_Open(void *arg1, char *path) {
Hardware_MouseDrivers_GPM *this = arg1;
printf("GPM: Opening %s...\n", path);
this->path = path;
}
I think this change would be easier and less complicated than (1) turning off the warnings, (2) documenting it so readers can understand why that warning isn't supposed to be important here, (3) documenting it some more so your readers actually believe that you know what you are doing, and (4) handling the problems that will occur if someone actually does port your code to TOPS-20.
I had this problem and after careful examination, I decided that I should not have gotten this message. Similar lines in the structure did not generate this error.
Using (void *) function_name fixed it.
This saved me from having to examine the gcc tree.

Resources