implicit declaration of function and undefined reference to - c

About compile suricata.
In Makefile,when CFLAGS wrap "-Werror-implicit-function-declaration"
I got the error:
detect-engine-siggroup.c: In function ‘SigGroupHeadFree’:
detect-engine-siggroup.c:187:9: error: implicit declaration of function ‘_mm_free’ [-Werror=implicit-function-declaration]
SCFreeAligned(sgh->mask_array);
^
detect-engine-siggroup.c: In function ‘SigGroupHeadBuildHeadArray’:
detect-engine-siggroup.c:1715:5: error: implicit declaration of function ‘_mm_malloc’ [-Werror=implicit-function-declaration]
sgh->mask_array = (SignatureMask *)SCMallocAligned((cnt * sizeof(SignatureMask)), 16);
When I delete "-Werror-implicit-function-declaration" in Makefile,I will got the error:
detect-engine-siggroup.o: In function `SigGroupHeadFree':
/root/suricata/suricata-2.0.9/src/detect-engine-siggroup.c:187: undefined reference to `_mm_free'
detect-engine-siggroup.o: In function `SigGroupHeadBuildHeadArray':
/root/suricata/suricata-2.0.9/src/detect-engine-siggroup.c:1715: undefined reference to `_mm_malloc'
Note:_mm_free and _mm_malloc is define in util-mem.h
Yet,I add some code in the other source file,but not in detect-engine-siggroup.c and util-mem.h.
What's wrong?
in detect-engine-siggroup.c(note I have deleted some redundant code here):
void SigGroupHeadFree(SigGroupHead *sgh)
{
if (sgh == NULL)
return;
SCLogDebug("sgh %p", sgh);
PatternMatchDestroyGroup(sgh);
#if defined(__SSE3__) || defined(__tile__)
if (sgh->mask_array != NULL) {
/* mask is aligned */
SCFreeAligned(sgh->mask_array);
sgh->mask_array = NULL;
}
#endif
if (sgh->head_array != NULL) {
SCFree(sgh->head_array);
sgh->head_array = NULL;
}
if (sgh->match_array != NULL) {
detect_siggroup_matcharray_free_cnt++;
detect_siggroup_matcharray_memory -= (sgh->sig_cnt * sizeof(Signature *));
SCFree(sgh->match_array);
sgh->match_array = NULL;
}
sgh->sig_cnt = 0;
if (sgh->init != NULL) {
SigGroupHeadInitDataFree(sgh->init);
sgh->init = NULL;
}
SCFree(sgh);
detect_siggroup_head_free_cnt++;
detect_siggroup_head_memory -= sizeof(SigGroupHead);
return;
}
in util-mem.h(note I have deleted some redundant code here):
#ifndef __UTIL_MEM_H__
#define __UTIL_MEM_H__
#include "util-atomic.h"
#if CPPCHECK==1
#define SCMalloc malloc
#define SCCalloc calloc
#define SCRealloc realloc
#define SCFree free
#define SCStrdup strdup
#define SCMallocAligned _mm_malloc
#define SCFreeAligned _mm_free
#else /* CPPCHECK */
#if defined(_WIN32) || defined(__WIN32)
#include "mm_malloc.h"
#endif
#if defined(__tile__)
/* Need to define __mm_ function alternatives, since these are SSE only.
*/
#include <malloc.h>
#define _mm_malloc(a,b) memalign((b),(a))
#define _mm_free(a) free((a))
#endif /* defined(__tile__) */
SC_ATOMIC_EXTERN(unsigned int, engine_stage);
/* Use this only if you want to debug memory allocation and free()
* It will log a lot of lines more, so think that is a performance killer */
/* Uncomment this if you want to print memory allocations and free's() */
//#define DBG_MEM_ALLOC
#ifdef DBG_MEM_ALLOC
#define SCFree(a) ({ \
extern uint8_t print_mem_flag; \
if (print_mem_flag == 1) { \
SCLogInfo("SCFree at %p", (a)); \
} \
free((a)); \
})
#else /* !DBG_MEM_ALLOC */
#define SCFree(a) ({ \
free(a); \
})
#if defined(__WIN32) || defined(_WIN32)
#define SCFreeAligned(a) ({ \
_mm_free(a); \
})
#else /* !win */
#define SCFreeAligned(a) ({ \
_mm_free((a)); \
})
#endif /* __WIN32 */
#endif /* DBG_MEM_ALLOC */
#endif /* CPPCHECK */
#endif /* __UTIL_MEM_H__ */
#endif /* DBG_MEM_ALLOC */
#endif /* CPPCHECK */
#endif /* __UTIL_MEM_H__ */
/*********************************************************************/
Now solved the problem,reason is forgetting to #include <pmmintrin.h> /* for SSE3 */
/*********************************************************************/

It looks like you have not included util-mem.h properly. SCFreeAligned seem to expand to _mm_free, but _mm_free doesn't seem to expand. Looking at the header file the definition of _mm_free seem to be dependent on __title__ being defined.
Then the compiler just sees a call to _mm_free which is given an implicit prototype as _mm_free doesn't exist. Then of course _mm_free will not be found during linking.

Related

How to use customize assert marco

tmp2.c
/*
gcc -Wall -Werror -g assert.c tmp2.c && ./a.out
*/
#include "tmp2.h"
#include <assert.h>
int main(void)
{
// assert(1 == 2);
Assert(1 == 2);
return 0;
}
tmp2.h
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <math.h>
#include<stdint.h>
#include<stdalign.h>
#include<stdbool.h>
/*
* BoolIsValid
* True iff bool is valid.
*/
#define BoolIsValid(boolean) ((boolean) == false || (boolean) == true)
/*
* PointerIsValid
* True iff pointer is valid.
*/
#define PointerIsValid(pointer) ((const void*)(pointer) != NULL)
extern void
ExceptionalCondition(const char *conditionName,
const char *fileName,
int lineNumber);
/*
* USE_ASSERT_CHECKING, if defined, turns on all the assertions.
* - plai 9/5/90
*
* It should _NOT_ be defined in releases or in benchmark copies
*/
/*
* Assert() can be used in both frontend and backend code. In frontend code it
* just calls the standard assert, if it's available. If use of assertions is
* not configured, it does nothing.
*/
#define USE_ASSERT_CHECKING 0
#ifndef USE_ASSERT_CHECKING
#define Assert(condition) ((void)true)
#define AssertMarcod(condition) ((void)true)
#elif defined(FRONTEND)
#include<assert.h>
#define Assert(p) assert(p)
#define AssertMarco(p) ((void) assert(p))
#else
/*
* Assert
* Generates a fatal exception if the given condition is false.
*/
#define Assert(condition) \
do { \
if (!(condition)) \
ExceptionalCondition(#condition,__FILE__,__LINE__); \
} while (0)
/*
* AssertMacro is the same as Assert but it's suitable for use in
* expression-like macros, for example:
*
* #define foo(x) (AssertMacro(x != 0), bar(x))
*/
#define AssertMacro(condition) \
((void) ((condition) || \
(ExceptionalCondition(#condition,__FILE__,__LINE__),0)))
#endif
assert.c
#include "tmp2.h"
#include <unistd.h>
#ifdef HAVE_EXECINFO_H
#include <execinfo.h>
#endif
/*
* ExceptionalCondition - Handles the failure of an Assert()
*
* We intentionally do not go through elog() here, on the grounds of
* wanting to minimize the amount of infrastructure that has to be
* working to report an assertion failure.
*/
void
ExceptionalCondition(const char *conditionName,
const char *fileName,
int lineNumber)
{
/* Report the failure on stderr (or local equivalent) */
if (!PointerIsValid(conditionName)
|| !PointerIsValid(fileName))
fprintf(stderr,"TRAP: ExceptionalCondition: bad arguments in PID %d\n",
(int) getpid());
else
fprintf(stderr,"TRAP: failed Assert(\"%s\"), File: \"%s\", Line: %d, PID: %d\n",
conditionName, fileName, lineNumber, (int) getpid());
/* Usually this shouldn't be needed, but make sure the msg went out */
fflush(stderr);
// /* If we have support for it, dump a simple backtrace */
// #ifdef HAVE_BACKTRACE_SYMBOLS
// {
// void *buf[100];
// int nframes;
// nframes = backtrace(buf, lengthof(buf));
// backtrace_symbols_fd(buf, nframes, fileno(stderr));
// }
// #endif
/*
* If configured to do so, sleep indefinitely to allow user to attach a
* debugger. It would be nice to use pg_usleep() here, but that can sleep
* at most 2G usec or ~33 minutes, which seems too short.
*/
#ifdef SLEEP_ON_ASSERT
sleep(1000000);
#endif
abort();
}
In this context, I'm trying a way to use the AssertMacro; that is, find a way to invoke assert.c ExceptionalCondition function. Assume FRONTEND is not defined. USE_ASSERT_CHECKING can be 1 or 0.
update: to use ExceptionalCondition function I need to declare it on tmp2.h via
extern void
ExceptionalCondition(const char *conditionName,
const char *fileName,
int lineNumber);
I also need to define USE_ASSERT_CHECKING in tmp2.h or before tmp2.h.
If I don't define USE_ASSERT_CHECKING seems all the assert will be true always?

meet "called object is not a function" error when use macro to Initialization tree data

I want to implement the Lisp Cons type in C, so I use link list to achieve it.
At the same time, I use a lot of macros to simpilfy the data creation.
The code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
* Macro Utils
*/
#define create_m(type) ((type *) malloc(sizeof(type)))
#define new_m(type, ...) ({ \
type * __t = create_m(type); \
*__t = (type){ __VA_ARGS__ }; \
__t; })
/*
* Type Define
*/
typedef struct atom Atom;
enum ATOM_TYPES;
// Cons Type
typedef Atom * Cons[2];
#define car(c) (c[0])
#define cdr(c) (c[1])
#define new_cons_m(car, cdr) ({ \
Cons * __c = create_m(Cons); \
car(__c) = car; \
cdr(__c) = cdr; })
// Id Type
typedef char * Id;
#define new_id_m(id) (strdup(id))
// Container Type
enum ATOM_TYPES {
ATOM_CONS, ATOM_ID
};
struct atom {
enum ATOM_TYPES type;
union {
Cons value_cons;
Id value_id;
void * value;
};
};
#define new_atom_m(t, ...) (new_m(Atom, .type = t, __VA_ARGS__))
#define new_atom_cons_m(car, cdr) ( \
new_atom_m(ATOM_CONS, .value_cons = new_cons_m(car, cdr)) )
#define new_atom_id_m(id) ( \
new_atom_m(ATOM_CONS, .value_id = new_id_m(id)) )
int main() {
printf("start program\n");
Atom * test = new_atom_cons_m(
new_atom_id_m("lisp"),
new_atom_cons_m(
new_atom_id_m("log"),
new_atom_id_m("say hello")
)
);
return 0;
}
And it failed to compile, with the following log:
arane.c: In function ‘main’:
arane.c:16:27: error: called object is not a function or function pointer
#define new_m(type, ...) ({ \
^
arane.c:18:18: note: in definition of macro ‘new_m’
*__t = (type){ __VA_ARGS__ }; \
^~~~~~~~~~~
arane.c:68:3: note: in expansion of macro ‘new_atom_m’
new_atom_m(ATOM_CONS, .value_cons = new_cons_m(car, cdr)) )
^~~~~~~~~~
arane.c:68:39: note: in expansion of macro ‘new_cons_m’
new_atom_m(ATOM_CONS, .value_cons = new_cons_m(car, cdr)) )
^~~~~~~~~~
arane.c:92:17: note: in expansion of macro ‘new_atom_cons_m’
Atom * test = new_atom_cons_m(
^~~~~~~~~~~~~~~
arane.c:66:29: note: in expansion of macro ‘new_m’
#define new_atom_m(t, ...) (new_m(Atom, .type = t, __VA_ARGS__))
^~~~~
arane.c:70:3: note: in expansion of macro ‘new_atom_m’
new_atom_m(ATOM_CONS, .value_id = new_id_m(id)) )
^~~~~~~~~~
arane.c:93:5: note: in expansion of macro ‘new_atom_id_m’
new_atom_id_m("lisp"),
^~~~~~~~~~~~~
...and much more errors
I think it is because there are some expressions in function call's argument list. I am seeking for some way to solve it, I use gcc7.5 to finish my work, if needed, I can upgrade it.
-----------2022-01-24-14:15-----------
The problem is solved, with some twest in code, however, I still don't really understand how it was happend.
The code changed as below:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
* Macro Utils
*/
#define create_m(type) ((type *) malloc(sizeof(type)))
#define new_m(type, ...) ({ \
type * __t = create_m(type); \
*__t = (type){ __VA_ARGS__ }; \
__t; })
/*
* Type Define
*/
typedef struct atom Atom;
enum ATOM_TYPES;
// Cons Type
typedef Atom * Cons[2];
#define car(c) (c[0])
#define cdr(c) (c[1]) // deletes here
// Id Type
typedef char * Id;
#define new_id_m(id) (strdup(id))
// Container Type
enum ATOM_TYPES {
ATOM_CONS, ATOM_ID
};
struct atom {
enum ATOM_TYPES type;
union {
Cons value_cons;
Id value_id;
void * value;
};
};
#define new_atom_m(t, ...) (new_m(Atom, .type = t, __VA_ARGS__))
#define new_atom_cons_m(car, cdr) ( \
new_atom_m(ATOM_CONS, .value_cons[0] = car, .value_cons[1] = cdr) )
#define new_atom_id_m(id) ( \ // changes here
new_atom_m(ATOM_CONS, .value_id = new_id_m(id)) )
int main() {
printf("start program\n");
Atom * test = new_atom_cons_m(
new_atom_id_m("lisp"),
new_atom_cons_m(
new_atom_id_m("log"),
new_atom_id_m("say hello")
)
);
// Atom * test = new_atom_cons_m(NULL, NULL);
return 0;
}

how to invoke global variables in dynamic link library?

I have 3 .c source files: common.c, interface_1.c, interface_2.c.
In common.c, I define some functions and global variables, and in interface_1.c and interface_2.c, these functions and global variables will be invoked.
Now, interface_1.c and interface_2.c will be compiled to .dll so as to be used by other program. The problem is that, while two dll files are called, global variables defined in common.c should be the same, which means: if a global variable is changed during the process of calling interface_1.dll, the same variable in interface_2.dll should be changed at the same time.
Background
I want to use PLECS to do power electronics simulation. There is a block called DLL which is very powerful. User can write c/cpp code and compile them to dynamic link library. Each DLL block can only call one .dll file. I have two DLL blocks and want to make a global variable to communicate between them.
The template of c source file which will be compile to dll are shown below.
DllHeader.h
#ifndef PLECSDLLHEADER_H_
#define PLECSDLLHEADER_H_
#if defined _WIN32
#define DLLEXPORT __declspec(dllexport)
#elif __GNUC__ >=4
#define DLLEXPORT __attribute__ ((visibility("default")))
#else
#define DLLEXPORT
#endif
#ifdef __cplusplus
extern "C" {
#endif
#pragma pack(push, 4)
struct SimulationSizes {
int numInputs; /* the number of inputs that the DLL needs */
int numOutputs; /* the number of outputs that the DLL provides */
int numStates; /* the number of discrete states that the DLL needs */
int numParameters; /* the number of user parameters that the DLL needs */
};
struct SimulationState {
const double* const inputs; /* array of input values (read-only) */
double* const outputs; /* array of output values (to fill by DLL) */
double* const states; /* array of discrete states (read/write) */
const double* const parameters; /* array of parameters (read-only) */
const double time; /* current simulation time (read-only) */
const char* errorMessage; /* error message to set by DLL */
void* userData; /* pointer to any DLL data (untouched by PLECS) */
};
#pragma pack(pop)
/* Required: DLL needs to set all fields in aSizes. */
/* Called once before the simulation. */
DLLEXPORT void plecsSetSizes(struct SimulationSizes* aSizes);
/* Optional: DLL may acquire resources, initialize states and outputs. */
/* Called once during the initialization of a new simulation. */
DLLEXPORT void plecsStart(struct SimulationState* aState);
/* Required: DLL needs to set outputs depending on inputs and states. */
/* Called whenever the simulation time reaches a multiple of the sample */
/* time. */
DLLEXPORT void plecsOutput(struct SimulationState* aState);
/* Optional: DLL may release any acquired resources. */
/* Called when the simulation is finished, even when an error occured. */
DLLEXPORT void plecsTerminate(struct SimulationState* aState);
#ifdef __cplusplus
}
#endif
#endif /* PLECSDLLHEADER_H_ */
interface.c
#include "DllHeader.h"
//Map input and output parameters to meaningful names
#define in aState->inputs[0]
#define out aState->outputs[0]
DLLEXPORT void plecsSetSizes(struct SimulationSizes* aSizes)
{
aSizes->numInputs = 1;
aSizes->numOutputs = 1;
aSizes->numStates = 0;
aSizes->numParameters = 0; //number of user parameters passed in
}
//This function is automatically called at the beginning of the simulation
DLLEXPORT void plecsStart(struct SimulationState* aState)
{
// do some initialization ...
}
//This function is automatically called every sample time
//output is written to DLL output port after the output delay
DLLEXPORT void plecsOutput(struct SimulationState* aState)
{
// do some calculation ...
}
Using LoadLibrary works. Be careful that in interface.c full path of common.dll should be specified! Solution is shown at the end.
For Lundin, it's involved in embedded development, some variables are time-based, which means they are alive all the time and invoked by other control functions. For example, a signal is sampled and passed to a variable, this sampled data will be used in several place, such as filter, closed-loop control... So it's difficult to decouple these messy usage...
common.h
#ifndef COMMON_H_
#define COMMON_H_
#if defined _WIN32
#define DLLEXPORT __declspec(dllexport)
#elif __GNUC__ >=4
#define DLLEXPORT __attribute__ ((visibility("default")))
#else
#define DLLEXPORT
#endif
#ifdef __cplusplus
extern "C" {
#endif
#pragma pack(push, 4)
typedef struct{
float a;
float b;
} Coord;
#pragma pack(pop)
extern Coord curPos;
DLLEXPORT Coord GetcurPos(void);
DLLEXPORT float getMax(float a, float b);
DLLEXPORT void SetcurPos(float a, float b);
#ifdef __cplusplus
}
#endif
#endif /* COMMON_H_ */
common.c
#include "common.h"
Coord curPos;
DLLEXPORT float getMax(float a, float b){
return a>b?a:b;
}
DLLEXPORT Coord GetcurPos(void){
return curPos;
}
DLLEXPORT void SetcurPos(float a, float b){
curPos.a=a;
curPos.b=b;
}
interface_a.c
#include "DllHeader.h"
#include <windows.h>
#include "common.h"
//Map input and output parameters to meaningful names
#define in aState->inputs[0]
#define out aState->outputs[0]
HMODULE module;
typedef float(*AddFunc)(float, float);
typedef Coord (*PosGetter)(void);
AddFunc dllmax;
PosGetter getCurPos;
DLLEXPORT void plecsSetSizes(struct SimulationSizes* aSizes)
{
aSizes->numInputs = 1;
aSizes->numOutputs = 1;
aSizes->numStates = 0;
aSizes->numParameters = 0; //number of user parameters passed in
}
DLLEXPORT void plecsStart(struct SimulationState* aState)
{
module = LoadLibrary(TEXT("D:\\Simulation\\PLECSLearn\\DLL\\global_test\\common.dll"));
if (module == NULL)
{
aState->errorMessage = "Failed to load common.dll";
}
dllmax = (AddFunc)GetProcAddress(module, "getMax");
getCurPos = (PosGetter)GetProcAddress(module, "GetcurPos");
}
//This function is automatically called every sample time
//output is written to DLL output port after the output delay
DLLEXPORT void plecsOutput(struct SimulationState* aState)
{
if (getCurPos().a == 1){
out = 2;
} else {
out = -1;
}
// out = dllmax(200,300);
}
interface_b.c
#include "DllHeader.h"
#include <windows.h>
#include "common.h"
//Map input and output parameters to meaningful names
#define in aState->inputs[0]
#define out aState->outputs[0]
HMODULE module;
typedef float(*AddFunc)(float, float);
typedef Coord (*PosGetter)(void);
typedef void (*PosSetter)(float, float);
AddFunc dllmax;
PosGetter getCurPos;
PosSetter setCurPos;
DLLEXPORT void plecsSetSizes(struct SimulationSizes* aSizes)
{
aSizes->numInputs = 1;
aSizes->numOutputs = 1;
aSizes->numStates = 0;
aSizes->numParameters = 0; //number of user parameters passed in
}
DLLEXPORT void plecsStart(struct SimulationState* aState)
{
module = LoadLibrary(TEXT("D:\\Simulation\\PLECSLearn\\DLL\\global_test\\common.dll"));
if (module == NULL)
{
aState->errorMessage = "Failed to load common.dll";
}
dllmax = (AddFunc)GetProcAddress(module, "getMax");
getCurPos = (PosGetter)GetProcAddress(module, "GetcurPos");
setCurPos = (PosSetter)GetProcAddress(module, "SetcurPos");
}
//This function is automatically called every sample time
//output is written to DLL output port after the output delay
DLLEXPORT void plecsOutput(struct SimulationState* aState)
{
static int cnt = 0;
if (cnt<5000){
setCurPos(0,0);
}else{
setCurPos(1,2);
}
cnt++;
out = getCurPos().a;
}

Preprocessor definitions not working in C

I've been frantically trying to get this following code to work. The preprocessor definitions WIDR and LIDR aren't working and it's giving me the compile error:
projects/elcain.c: In function ‘main’:
projects/elcain.c:17:6: error: ‘WIDR’ undeclared (first use in this function)
if ( WIDR ) {
^
projects/elcain.c:17:6: note: each undeclared identifier is reported only once for each function it appears in
projects/elcain.c:19:13: error: ‘LIDR’ undeclared (first use in this function)
} else if ( LIDR ) {
I don't really have experience with preprocessor macros, or the preprocessor in general, so go easy on me.
Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
#define WIDR 1
#elif defined _linux_
#define LIDR 1
#endif
int main () {
char* directory = (char*) malloc (1);
if ( WIDR ) {
strcpy(directory, "C:\\TEMP\\");
} else if ( LIDR ) {
strcpy(directory, "~/.temp/");
} else {
*directory = 0x00;
}
printf("%s\n", directory);
return 0;
}
You probably simply want this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main () {
#ifdef _WIN32
char directory[] = "C:\\TEMP\\";
#elif defined _linux_
char directory[] = "~/.temp/";
#else
#error Neither _WIN32 nor _linux_ are defined
#endif
printf("%s\n", directory);
return 0;
}
What you are looking for is something like this:
#include <stdlib.h>
#if defined unix || \
defined __unix || \
defined __unix__ || \
defined __linux__ || \
defined __FreeBSD__ || \
defined __CYGWIN__ || \
(defined __APPLE__ && defined __MACH__)
static const char TMP_DIR[] = "~/.temp/";
#elif defined WIN32 || \
defined _WIN32 || \
defined __WIN32
static const char TMP_DIR[] = "C:\\TEMP\\";
#else
#error "Platform not supported"
#endif
int
main(void)
{
printf("%s\n", TMP_DIR);
return EXIT_SUCCESS;
}
In fact both WIDR and LIDR are conditional compilation directives. In other words they exist at compilation time only.
Change your code like this:
#ifdef WIDR
strcpy(directory, "C:\\TEMP\\");
#elif defined LDIR
strcpy(directory, "~/.temp/");
#else
*directory = 0x00;
#endif
then compilation errors will gone

Preproccesor macro to

Im trying to create a preprocessor macro to allocate and free memory for matrix/vector of any data type. Here is what I have so far:
#ifndef H_ARRAY_H
#define H_ARRAY_H
#include "xmalloc.h"
#define make_vector(v,n) (v = xmalloc( (n) * sizeof *(v))
#define free_vector(v) do { free(v) ; v = NULL; } while(0)
#define make_matrx(a , m , n) do { \
size_t make_matrix_loop_counter; \
make_vector(a, (m) + 1); \
for ( make_matrix_loop_counter = 0; make_matrix_loop_counter < (m) ; make_matrix_loop_counter++) \
make_vector((a)[make_matrix_loop_counter], (n)); \
(a)[m] = NULL; \
} while (0)
#define free_matrix(a) do { \
if (a != NULL){ \
size_t make_matrix_loop_counter; \
for (make_matrix_loop_counter = 0 ; (a) [make_matrix_loop_counter] != NULL; make_matrix_loop_counter++) \
free_vector((a)[make_matrix_loop_counter]); \
free_vector(a); \
a != NULL; \
} \
} while (0)
But when I try to construct a matrix it spits out an error "implicit declaration of function ‘make_matrix’".
Any suggestions.
PS: xmalloc.h allocate space
Are you sure your MACRO name should read make_matrx instead of make_matrix?
You need to correct the macro name spelling. Otherwise, when you use make_matrix() in your code, it does not find a corresponding function.

Resources