I have two cross cutting concerns in my design of my software. The memory allocator tracks memory usage in its struct(class) member variables. I also have a logger. Right now I am passing the logger and the allocator into the constructor of my objects. I can maintain a reference to them but then I would have to do that in every struct(class) I create. It would be nice if they were global but I am not sure how to do that in C. Can I construct a global memory allocator that will correctly keep track of bytes used without passing it in to my functions calls to reference?
EDIT:
I am trying to use object_tracker as a global variable in my create and destroy functions. When I compile and test the files below this is the result I get: How do I use extern correctly to get the global reference to work?
gcc -I ../include object_tracker.c test_file.c test_main.c -o test
./test
/tmp/ccuT8Z1A.o: In function `Test_Create':
test_file.c:(.text+0xb): undefined reference to `object_tracker'
/tmp/ccuT8Z1A.o: In function `Test_Destroy':
test_file.c:(.text+0x4b): undefined reference to `object_tracker'
collect2: error: ld returned 1 exit status
test_file.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "object_tracker.h"
#include "test_file.h"
struct Test* Test_Create() {
struct Test* test = (struct Test*)Object_Tracker_Obj_Alloc(object_tracker, 1, sizeof(struct Test));
test->foobar = 10;
return test;
}
void Test_Destroy(struct Test* test) {
if(test != NULL) {
Object_Tracker_Obj_Free(object_tracker, test);
}
}
test_file.h
#ifndef _TEST_FILE_H_
#define _TEST_FILE_H_
#include "object_tracker.h"
extern struct Object_Tracker* object_tracker;
struct Test {
int foobar;
};
struct Test* Test_Create();
void Test_Destroy(struct Test* test);
#endif
test_main.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "object_tracker.h"
#include "test_file.h"
int main(int argc, char* argv[]) {
struct Object_Tracker* object_tracker = Object_Tracker_Create();
struct Test* test = Test_Create();
Test_Destroy(test);
printf("heello\n");
}
Yes you can do that in C, just define the global memory allocator at the top of the file, and everything below it will know its existence.
In order for other files to have an eye on it, use extern, as explained in How do I share a global variable between c files?
Keep in mind though that global variables should be avoided when possible.
I removed the extern keyword and made a globals.h file with the declaration for object_tracker. I included it every "class" file and it works. I am still not sure what the extern keyword is used for.
According to your example there is no variable ‘object_tracker’ defined globally. You have define such variable, but it is inside main function.
struct Object_Tracker* object_tracker = Object_Tracker_Create();//Inside main function ???
Since it is defined inside main function is it not visible to other functions.
So move this definition to global scope. The updated test_main.c is as below.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "object_tracker.h"
#include "test_file.h"
struct Object_Tracker* object_tracker; //Global scope variable
int main(int argc, char* argv[]) {
object_tracker = Object_Tracker_Create(); //Assign value for the variable
struct Test* test = Test_Create();
Test_Destroy(test);
printf("heello\n");
}
Related
this a reproducible example and not the entire code the entire code is too large..
my problem was that i had a structure that i created using malloc and i needed to access it from another function in another file, but i keep getting segfault...
header file
main.h
#ifndef main_a
#define main_a
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct cmd_s
{
int n;
} cmd_t;
extern cmd_t *ptr;
void push(char *line);
#endif
the main.c file
main.c
#include "main.h"
cmd_t *ptr = NULL;
int main(void)
{
cmd_t *ptr = malloc(sizeof(cmd_t));
ptr->n = 5;
push("line");
return (0);
}
and where i need to access the struct from named opcode.c
opcode.c
#include "main.h"
void push(char *line)
{
int new = ptr->n;
}
note that this is not the actual code the actual code has useful values, this is an example that contains the challenge i am facing
i tried to use static instead but i got the same error.
i'm still a novice in c programming..
and i don't want to change the way i created the structure, which is through malloc because another function depends on it... i just need to make that malloced structure accessible to another file in the program.
thanks.
int main(void)
{
cmd_t *ptr = malloc(sizeof(cmd_t));
You create new ptr variable visible only in function main. Your push see the global pointer ptr but not the one you have malloced.
You need to
int main(void)
{
ptr = malloc(sizeof(*ptr));
/* .... */
Use obiects not types in sizeof (as in this example)
My compiler (GCC) is giving me the warning:
warning: implicit declaration of function
Why is it coming?
You are using a function for which the compiler has not seen a declaration ("prototype") yet.
For example:
int main()
{
fun(2, "21"); /* The compiler has not seen the declaration. */
return 0;
}
int fun(int x, char *p)
{
/* ... */
}
You need to declare your function before main, like this, either directly or in a header:
int fun(int x, char *p);
The right way is to declare function prototype in header.
Example
main.h
#ifndef MAIN_H
#define MAIN_H
int some_main(const char *name);
#endif
main.c
#include "main.h"
int main()
{
some_main("Hello, World\n");
}
int some_main(const char *name)
{
printf("%s", name);
}
Alternative with one file (main.c)
static int some_main(const char *name);
int some_main(const char *name)
{
// do something
}
When you do your #includes in main.c, put the #include reference to the file that contains the referenced function at the top of the include list.
e.g. Say this is main.c and your referenced function is in "SSD1306_LCD.h"
#include "SSD1306_LCD.h"
#include "system.h" #include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include <string.h>
#include <math.h>
#include <libpic30.h> // http://microchip.wikidot.com/faq:74
#include <stdint.h>
#include <stdbool.h>
#include "GenericTypeDefs.h" // This has the 'BYTE' type definition
The above will not generate the "implicit declaration of function" error, but below will-
#include "system.h"
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include <string.h>
#include <math.h>
#include <libpic30.h> // http://microchip.wikidot.com/faq:74
#include <stdint.h>
#include <stdbool.h>
#include "GenericTypeDefs.h" // This has the 'BYTE' type definition
#include "SSD1306_LCD.h"
Exactly the same #include list, just different order.
Well, it did for me.
You need to declare the desired function before your main function:
#include <stdio.h>
int yourfunc(void);
int main(void) {
yourfunc();
}
When you get the error: implicit declaration of function it should also list the offending function. Often this error happens because of a forgotten or missing header file, so at the shell prompt you can type man 2 functionname and look at the SYNOPSIS section at the top, as this section will list any header files that need to be included. Or try http://linux.die.net/man/ This is the online man pages they are hyperlinked and easy to search.
Functions are often defined in the header files, including any required header files is often the answer. Like cnicutar said,
You are using a function for which the compiler has not seen a
declaration ("prototype") yet.
If you have the correct headers defined & are using a non GlibC library (such as Musl C) gcc will also throw error: implicit declaration of function when GNU extensions such as malloc_trim are encountered.
The solution is to wrap the extension & the header:
#if defined (__GLIBC__)
malloc_trim(0);
#endif
This error occurs because you are trying to use a function that the compiler does not understand. If the function you are trying to use is predefined in C language, just include a header file associated with the implicit function.
If it's not a predefined function then it's always a good practice to declare the function before the main function.
Don't forget, if any functions are called in your function, their prototypes must be situated above your function in the code. Otherwise, the compiler might not find them before it attempts to compile your function. This will generate the error in question.
The GNU C compiler is telling you that it can find that particular function name in the program scope. Try defining it as a private prototype function in your header file, and then import it into your main file.
I think the question is not 100% answered. I was searching for issue with missing typeof(), which is compile time directive.
Following links will shine light on the situation:
https://gcc.gnu.org/onlinedocs/gcc-5.3.0/gcc/Typeof.html
https://gcc.gnu.org/onlinedocs/gcc-5.3.0/gcc/Alternate-Keywords.html#Alternate-Keywords
as of conculsion try to use __typeof__() instead. Also gcc ... -Dtypeof=__typeof__ ... can help.
A toy code illustrating my problem is as follows:
stuff.h:
#ifndef STUFF
#define STUFF
int a;
int testarr[]={1,2,3};
#endif
fcn.h:
#include "stuff.h"
int b[]={5,6,7};
void fcn();
main.h:
#include "stuff.h"
#include <stdio.h>
fcn.c:
#include "main.h"
void fcn() {
printf("Hello\n");
}
main.c:
#include "main.h"
#include "fcn.h"
int main() {
fcn();
printf("HI\n");
}
An attempt to compile fails with:
/g/pe_19976/fcn_2.o:(.data+0x40): multiple definition of `testarr'
/g/pe_19976/main_1.o:(.data+0x40): first defined here
After doing some reading, I realize that defining the array testarr in the header file is a problem. But the thing is, in my real code, several files need access to testarr and it needs to have the same assigned values everywhere. I guess I could put it in main.h (?) but even if that would work, in my real code it logically belongs in stuff.h. How do I solve this conundrum?
BTW, based on something else I found, I tried defining testarr as extern but got the same problem.
When you put a variable definition into a header file, any .c file that includes it will have a copy of that variable. When you then attempt to link them, you get a multiple definition error.
Your header files should contain only a declaration of the variable. This is done using the extern keyword, and with no initializer.
Then in exactly one .c file, you put the definition along with an optional initializer.
For example:
main.c:
#include "main.h"
#include "fcn.h"
int a;
int testarr[]={1,2,3};
int main() {
fcn();
printf("HI\n");
}
stuff.h:
#ifndef STUFF
#define STUFF
extern int a;
extern int testarr[];
#endif
fcn.h:
#include "stuff.h"
extern int b[];
void fcn();
fcn.c:
#include "main.h"
int b[]={5,6,7};
void fcn() {
printf("Hello\n");
}
It is not clear why you are using so many global variables. The array
int testarr[]={1,2,3};
is defined as many times as there are compilation units (in your example there are at least two compilation units) that include the corresponding header.
Declare the array in a header like
extern int testarr[3];
and define it in a cpp module.
int testarr[]={1,2,3};
The same is valid for other global variables that have external linkage.
As for this remark
BTW, based on something else I found, I tried defining testarr as
extern but got the same problem.
Then the array with the specifier extern shall not be initialized in a header. Otherwise it is a definition of the array.
I want to return a struct and print one of its members in main.
I am getting this error when trying to compile:
Main.c: In function ‘main’:
Main.c:8:2: error: invalid use of undefined type ‘struct busRoute’
Any help would be appreciated. I don't see why what I'm trying to do won't compile.
BusRoute.c
#include <stdio.h>
#include "BusRoute.h"
struct busRoute {
int busRouteNumber;
char *startingLocation;
char *endingLocation;
char driverName[36];
} route[STRUCT_SIZE] = {0};
//retrieves route info
struct busRoute getBusRouteInfo(unsigned int index)
{
return route[index];
}
void setStruct()
{
route[2].busRouteNumber = 5;
}
Main.c File
#include <stdio.h>
#include "BusRoute.h"
int main()
{
setStruct();
printf("%d",getBusRouteInfo(2).busRouteNumber);
}
Your struct busRoute should be defined in BusRoute.h, not BusRoute.c, if you want to use it in main.c. And you do want to use it in main.c, if your getBusRouteInfo() function returns one. Without main.c being able to see this definition, it doesn't know that struct busRoute even has a member named busRouteNumber, let alone how to get at it, so that's why compilation fails.
Your other option is to define a function like getBusRouteInfoRouteNumber(2), which will return the appropriate member indirectly. That way, main.c doesn't need to know anything about the actual struct busRoute.
I am trying to make the s_cord_print function visible in the cord_s.c file only. Currently the function is visible/runnable in main.c even when it is declared static.
How do I make the s_cord_print function private to cord_s.c?
Thanks!
s_cord.c
typedef struct s_cord{
int x;
int y;
struct s_cord (*print)();
} s_cord;
void* VOID_THIS;
#define $(EL) VOID_THIS=&EL;EL
static s_cord s_cord_print(){
struct s_cord *THIS;
THIS = VOID_THIS;
printf("(%d,%d)\n",THIS->x,THIS->y);
return *THIS;
}
const s_cord s_cord_default = {1,2,s_cord_print};
main.c
#include <stdio.h>
#include <stdlib.h>
#include "s_cord.c"
int main(){
s_cord mycord = s_cord_default;
mycord.x = 2;
mycord.y = 3;
$(mycord).print().print();
//static didn't seem to hide the function
s_cord_print();
return 0;
}
~
The problem is:
#include "s_cord.c"
You should remove that. Instead, create a s_cord.h file that contains only declarations, such as:
typedef struct s_cord{
int x;
int y;
struct s_cord (*print)();
} s_cord;
and put:
#include "s_cord.h"
in main.c and s_cord.c. You also need an extern declaration for s_cord_default. So the complete code is:
s_cord.c:
#include "s_cord.h"
#include <stdio.h>
void* VOID_THIS;
static s_cord s_cord_print(){
struct s_cord *THIS;
THIS = VOID_THIS;
printf("(%d,%d)\n",THIS->x,THIS->y);
return *THIS;
}
const s_cord s_cord_default = {1,2,s_cord_print};
s_cord.h:
typedef struct s_cord{
int x;
int y;
struct s_cord (*print)();
} s_cord;
#define $(EL) VOID_THIS=&EL;EL
extern const s_cord s_cord_default;
extern void *VOID_THIS;
main.c:
#include <stdio.h>
#include <stdlib.h>
#include "s_cord.h"
int main(){
s_cord mycord = s_cord_default;
mycord.x = 2;
mycord.y = 3;
$(mycord).print().print();
return 0;
}
You'll now get a error if you try to call s_cord_print() from main, as expected.
EDIT: I forgot to move the $(EL) definition, and it needed an extern for VOID_THIS.
EDIT 2: The correct compilation command is:
gcc s_cord.c main.c -o main
When you include s_cord.c from within main.c, the compiler sees your program as one big file. It doesn't treat the included file as separate. To make them separate, you have to compile them separately. Once you have compiled them separately, you will then have to link them to create the whole program.
When you try to compile each part, you will get errors, because each file doesn't know about the code in the other file. Remember, this is what you were trying to accomplish with that one function. Well, now you've got what you asked for, many times over. Now, you have to create header files that explain the "missing parts". Generally the files being compiled look at each other's ".h" files (they #include them) to get a bearing on the "missing" (actually, external) parts. These are declarations, which tell the compiler "pretend you already know about this, and I promise that when we link everything, it will be provided".