I have a test file (just for the link test) where I overload the new/delete operators with my own malloc/free library called libxmalloc.a. But I keep getting "undefined reference to" error as following when linking the static library, even I change the order of test.o and -lxmalloc. But everything works well with other C programs linking this library. I'm so confused with this issue and appreciate any clue.
Error Msg:
g++ -m64 -O3 -I/usr/include/ethos -I/usr/include/nacl/x86_64 -c -o test.o test.cpp
g++ -m64 -O3 -L. -o demo test.o -lxmalloc
test.o: In function `operator new(unsigned long)':
test.cpp:(.text+0x1): undefined reference to `malloc(unsigned long)'
test.o: In function `operator delete(void*)':
test.cpp:(.text+0x11): undefined reference to `free(void*)'
test.o: In function `operator new[](unsigned long)':
test.cpp:(.text+0x21): undefined reference to `malloc(unsigned long)'
test.o: In function `operator delete[](void*)':
test.cpp:(.text+0x31): undefined reference to `free(void*)'
test.o: In function `main':
test.cpp:(.text.startup+0xc): undefined reference to `malloc(unsigned long)'
test.cpp:(.text.startup+0x19): undefined reference to `malloc(unsigned long)'
test.cpp:(.text.startup+0x24): undefined reference to `free(void*)'
test.cpp:(.text.startup+0x31): undefined reference to `free(void*)'
collect2: ld returned 1 exit status
make: *** [demo] Error 1
My test.cpp file:
#include <dual/xalloc.h>
#include <dual/xmalloc.h>
void*
operator new (size_t sz)
{
return malloc(sz);
}
void
operator delete (void *ptr)
{
free(ptr);
}
void*
operator new[] (size_t sz)
{
return malloc(sz);
}
void
operator delete[] (void *ptr)
{
free(ptr);
}
int
main(void)
{
int *iP = new int;
int *aP = new int[3];
delete iP;
delete[] aP;
return 0;
}
My Makefile:
CFLAGS += -m64 -O3 -I/usr/include/ethos -I/usr/include/nacl/x86_64
CXXFLAGS += -m64 -O3
LIBDIR += -L.
LIBS += -lxmalloc
all: demo
demo: test.o
$(CXX) $(CXXFLAGS) $(LIBDIR) -o demo test.o $(LIBS)
test.o: test.cpp
$(CXX) $(CFLAGS) -c -o $# $<
clean:
- rm -f *.o demo
But everything works well with other C programs linking this library.
Did you notice that C and C++ compilation create different symbol names on object file level? It's called 'name mangling'.
The (C++) linker would show undefined references as demangled symbols in the error message, which might confuse you. If you inspect your test.o file with nm -u you'll see that the referenced symbol names don't match with those provided in your library.
If you want to use functions linked in as externals that were compiled using the plain C compiler, you'll need their function declarations enclosed in an extern "C" {} block which suppresses C++ name mangling for everything declared or defined inside, e.g.:
extern "C"
{
#include <dual/xalloc.h>
#include <dual/xmalloc.h>
}
Even better, you might wrap your function declarations in your header files like this:
#if defined (__cplusplus)
extern "C" {
#endif
/*
* Put plain C function declarations here ...
*/
#if defined (__cplusplus)
}
#endif
Related
There are two codes in Fortran and C++ with simple array manipulations with different declarations of arrays for C++. Let me know how to improve C++ code to get similar efficiency as in the Fortran code. The duration of runs in seconds is summarized below.
The Fortran program:
! fort.f90
PARAMETER ( N=1000000, M=10000 )
REAL*8, ALLOCATABLE :: D(:)
ALLOCATE(D(N))
A=1.0
DO J=1,M
DO I=1,N
D(I)=A+I+J
ENDDO
ENDDO
END
The Cpp program:
// main.cpp
using namespace std;
using namespace blitz;
int main(int argc, char* argv[]){
int N=1000000, M=10000;
double* D=new double[N];
//Array<double,1> D(N); // for Blitz C++
//vector<double>D(N);
//valarray<double>D(N);
const double a=1.0;
size_t i,j;
for (j=0; j<M; j++)
for (i=0; i<N; i++)
D[i]=a+i+j;
return 0;
}
g++ main.cpp -o main && time main
g++ main.cpp -o main -Ofast && time main
f95 fort.f90 -o fort && time fort
f95 fort.f90 -o fort -Ofast && time fort
Here is statistics:
1) double* D=new double[N]; g++: 58,1s, g++ -Ofast : 16,413s
2) valarrayD(N); ~ the same
3) vector; ~ the same
4) BlitzC++ ; g++ : 3m19,017s, g++ -Ofast : 15,142s
5) ALLOCATE(d(N)); f95 : 42,092s, f95 -Ofast : 0,002s
I'm trying to compile the following code
#include <iostream>
#include <windows.h>
#include <objbase.h>
int main (int argc, char** argv) {
HRESULT hr;
hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (SUCCEEDED(hr)) {
std::cout << "Initialized" << std::endl;
} else {
std::cout << "Failed" << std::endl;
}
CoUninitialize();
return 0;
}
but
g++ -o test -L"<dir>" -lOle32 <file>.cpp
# <dir> contains Ole32.Lib
always tells me that __imp_CoInitializeEx and __imp_CoUninitialize are undefined and -print-file-name=Ole32.Lib just return Ole32.Lib. If g++ doesn't find Ole32.Lib, maybe
g++ -c -o test.o <file>.cpp
ld -L"<dir>" -lOle32 -o test test.o
works. Now g++/ld actually finds CoInitializeEx and CoUninitialize, but the standard library seems to be missing and adding -static-libstdc++ or -lstdc++ or -llibstdc++ doesn't help either. So what am I missing? Why is g++ unable to find CoInitializeEx and CoUninitialize?
EDIT: I can definitely say that there is nothing wrong with my code, my header files and my library files, because I can compile the code using Visual Studios compiler:
cl /c /EHsc ^
/I"<...>\Microsoft Visual Studio 14.0\VC\include" ^
/I"<...>\Windows Kits\10\Include\<version>\ucrt" ^
/I"<...>\Windows Kits\10\Include\<version>\shared" ^
/I"<...>\Windows Kits\10\Include\<version>\um" ^
/Fotest.obj ^
main.cpp
link /nologo /machine:x64 /subsystem:console ^
/libpath:"<...>\Microsoft Visual Studio 14.0\VC\lib\amd64" ^
/libpath:"<...>\Windows Kits\10\Lib\<version>\ucrt\x64" ^
/libpath:"<...>\Windows Kits\10\Lib\<version>\um\x64" ^
/out:test.exe ^
test.obj Ole32.Lib
I'm using CMake on FreeBSD 11 within CLion and have the following CMakeLists.txt:
cmake_minimum_required(VERSION 3.7)
project(owm)
set(CMAKE_CXX_STANDARD 11)
set(SOURCE_FILES main.cpp owm.cpp owm.h)
add_executable(owm ${SOURCE_FILES})
set(LIBS ${LIBS})
find_package(X11 REQUIRED)
if (X11_FOUND)
include_directories(${X11_INCLUDE_DIR})
link_libraries(${X11_LIBRARIES})
endif(X11_FOUND)
file(GLOB MY_PUBLIC_HEADERS
"test/*"
)
file(COPY ${MY_PUBLIC_HEADERS} DESTINATION test)
Which seems to work fine, however when going to compile the project I get the following:
/usr/local/bin/cmake --build /home/cory/projects/owm/cmake-build-debug --target all -- -j 12
Scanning dependencies of target owm
[ 33%] Building CXX object CMakeFiles/owm.dir/owm.cpp.o
[ 66%] Linking CXX executable owm
CMakeFiles/owm.dir/owm.cpp.o: In function `owm::Create(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)':
/home/cory/projects/owm/owm.cpp:20: undefined reference to `XOpenDisplay'
/home/cory/projects/owm/owm.cpp:22: undefined reference to `XDisplayName'
CMakeFiles/owm.dir/owm.cpp.o: In function `owm::owm(_XDisplay*)':
/home/cory/projects/owm/owm.cpp:31: undefined reference to `XInternAtom'
/home/cory/projects/owm/owm.cpp:32: undefined reference to `XInternAtom'
CMakeFiles/owm.dir/owm.cpp.o: In function `owm::~owm()':
/home/cory/projects/owm/owm.cpp:37: undefined reference to `XCloseDisplay'
c++: error: linker command failed with exit code 1 (use -v to see invocation)
gmake[2]: *** [CMakeFiles/owm.dir/build.make:121: owm] Error 1
gmake[1]: *** [CMakeFiles/Makefile2:68: CMakeFiles/owm.dir/all] Error 2
gmake: *** [Makefile:84: all] Error 2
I'm not certain if this is relevant but message(FATAL_ERROR ${X11_LIBRARIES}) returns:
/usr/local/lib/libSM.so/usr/local/lib/libICE.so/usr/local/lib/libX11.so/usr/local/lib/libXext.so
And message(FATAL_ERROR ${X11_INCLUDE_DIR}) returns:
/usr/local/include
Within the offending file I have:
#include "owm.h"
extern "C" {
#include <X11/Xlib.h>
#include <X11/Xutil.h>
}
#include <iostream>
#include <cstring>
#include <algorithm>
template <typename T>
T* CHECK_NOTNULL(T* t) {
if (t == NULL) {
}
return (t);
}
std::unique_ptr<owm> owm::Create(const std::string& display_str) {
const char* display_c_str = (display_str.empty() ? nullptr : display_str.c_str());
Display* display = XOpenDisplay(display_c_str);
if (display == nullptr) {
std::cout << "Failed to open X display " << XDisplayName(display_c_str);
return (nullptr);
}
return (std::unique_ptr<owm>(new owm(display)));
}
owm::owm(Display *display)
: _display(CHECK_NOTNULL(display)),
_root(DefaultRootWindow(_display)),
WM_PROTOCOLS(XInternAtom(_display, "WM_PROTOCOLS", false)),
WM_DELETE_WINDOW(XInternAtom(_display, "WM_DELETE_WINDOW", false)) {
}
owm::~owm() {
XCloseDisplay(_display);
}
void owm::Run() {
}
Command link_libraries affects only on futher executables/libraries. From documentation:
Specify libraries or flags to use when linking any targets created later in the current directory or below by commands such as add_executable() or add_library().
So you need to either:
use link_libraries before add_executable or
use target_link_libraries instead (this is preferred way)
#include <iostream>
using namespace std;
int main()
{
constexpr double GetPi() {return 22.0/7;}
cout << GetPi() << endl;
}
No idea what is going on here. Please help me.
I've tried to compile this and even tried to re-format the code but it doesn't really help much. I thought this was the correct way you did things? What's going on here? It's a constant expression.
Here is the compilation error:
C:\Windows\system32\cmd.exe /C "C:/TDM-GCC-64/bin/mingw32-make.exe -j4` SHELL=cmd.exe -e -f Makefile"
"----------Building project:[ Constant_Expression - Debug ]----------"
mingw32-make.exe[1]: Entering directory 'C:/Program Files/CodeLite/CPP/Constants/Constant_Expression'
codelite-cc C:/TDM-GCC-64/bin/g++.exe -c "C:/Program Files/CodeLite/CPP/Constants/Constant_Expression/main.cpp" -g -O0 -std=c++11 -Wall -o ./Debug/main.cpp.o -I. -I.
C:/Program Files/CodeLite/CPP/Constants/Constant_Expression/main.cpp: In function 'int main()':
C:/Program Files/CodeLite/CPP/Constants/Constant_Expression/main.cpp:7:30: error: a function-definition is not allowed here before '{' token
constexpr double GetPi() {return 22.0/7;}
^
C:/Program Files/CodeLite/CPP/Constants/Constant_Expression/main.cpp:8:19: error: 'GetPi' was not declared in this scope
cout << GetPi() << endl;
^
mingw32-make.exe[1]: *** [Debug/main.cpp.o] Error 1
Constant_Expression.mk:93: recipe for target 'Debug/main.cpp.o' failed
mingw32-make.exe[1]: Leaving directory 'C:/Program Files/CodeLite/CPP/Constants/Constant_Expression'
mingw32-make.exe: *** [All] Error 2
Makefile:4: recipe for target 'All' failed
3 errors, 0 warnings
In C++ you are not allowed to define a function inside another function. (unlike closures in javascript).
You have to define GetPI() outside the main() function
#include <iostream>
using namespace std;
constexpr double GetPi() {return 22.0/7;}
int main()
{
cout << GetPi() << endl;
}
My Yacc source is in pos.yacc and my Lex source is in pos1.lex, as shown.
pos1.lex
%{
#include "y.tab.h"
int yylval;
%}
DIGIT [0-9]+
%%
{DIGIT} {yylval=atoi(yytext);return DIGIT;}
[\n ] {}
. {return *yytext;}
%%
pos.yacc
%token DIGIT
%%
s:e {printf("%d\n",$1);}
e:DIGIT {$$=$1;}
|e e "+" {$$=$1+$2;}
|e e "*" {$$=$1*$2;}
|e e "-" {$$=$1-$2;}
|e e "/" {$$=$1/$2;}
;
%%
main() {
yyparse();
}
yyerror() {
printf("Error");
}
Compilation errors
While compiling I am getting errors like:
malathy#malathy:~$ cc lex.yy.c y.tab.c -ly -ll
pos.y: In function ‘yyerror’:
pos.y:16: warning: incompatible implicit declaration of built-in function ‘printf’
pos.y: In function ‘yyparse’:
pos.y:4: warning: incompatible implicit declaration of built-in function ‘printf’
What causes those errors?
How am I supposed to compile Lex and Yacc source code?
printf() is defined in stdio.h so just include it above y.tab.h in pos1.lex:
%{
#include <stdio.h>
/* Add ^^^^^^^^^^^ this line */
#include "y.tab.h"
int yylval;
%}
DIGIT [0-9]+
%%
{DIGIT} {yylval=atoi(yytext);return DIGIT;}
[\n ] {}
. {return *yytext;}
%%
You have the direct answer to your question from trojanfoe - you need to include <stdio.h> to declare the function printf(). This is true in any source code presented to the C compiler.
However, you should also note that the conventional suffix for Yacc source is .y (rather than .yacc), and for Lex source is .l (rather than .lex). In particular, using those sufffixes means that make will know what to do with your source, rather than having to code the compilation rules by hand.
Given files lex.l and yacc.y, make compiles them to object code using:
$ make lex.o yacc.o
rm -f lex.c
lex -t lex.l > lex.c
cc -O -std=c99 -Wall -Wextra -c -o lex.o lex.c
yacc yacc.y
mv -f y.tab.c yacc.c
cc -O -std=c99 -Wall -Wextra -c -o yacc.o yacc.c
rm lex.c yacc.c
$
This is in a directory with a makefile that sets CFLAGS = -O -std=c99 -Wall -Wextra. (This was on MacOS X 10.6.6.) You will sometimes see other similar rules used; in particular, lex generates a file lex.yy.c by default (at least on MacOS X), and you'll often see a rule such as:
lex lex.l
mv lex.yy.c lex.c
cc -O -std=c99 -Wall -Wextra -c -o lex.o lex.c
Or even:
lex lex.l
cc -O -std=c99 -Wall -Wextra -c -o lex.o lex.yy.c
The alternatives are legion; use make and it gets it right.
Include header file stdio.h
for compilation
open terminal locate both files and type
lex pos1.l
yacc pos.y
cc lex.yy.c y.tab.h -ll
./a.out
You can follow these steps.
you just need to save in file
pos1.l and pos.y
I hope it will work