C++ math functions problem (under Linux)
I’m having problem regarding max and sqrt If I include math.h it coudn’t find sqrt. So I view the cmath header file and inside it includes math.h, but when I try to open math.h it says that file is not found. SO ithink my math.h is missing in Linux.
In linux, you’ll almost always find it at /usr/include/math.h. Are you sure it’s not there? It’s installed as part of the glibc or glibc-headers packages on many distros.
4 Answers 4
I just need to write it this way:
But Why does it work without «std::» under Windows OS?
It depends on your compiler. Some don’t correctly place the functions in the C standard library into the std namespace.
I think the windows.h header files define min and max as macros. They can be disabled by defining NOMINMAX before including said file.
NB: in C++ you should #include not #include
NB: also specifying the namespace is a good practice
It’s possible that the reason that you did not need to use std:: previously, is because somewhere in a headerfile the following statement was written:
After this statement, the ‘std::’ prefix is not necessary anymore.
Hope this clarified things.
Your system likely has the C headers in one place in the file system, and the C++ headers in another. Are you familiar with the actual list of directories searched for system headers? (Actually, the implementation is not required to have system header files, although all the ones I’m familiar with do. The C++ standard has requirements on what the statement #include has to do, but not on how it has to be done.)
In your answer, you talk about variations between C++ on Linux and Windows. These are not OS-specific, but rather implementation-specific. You’re probably using Visual C++ on Windows and something else on Linux (if only because VC++ runs only on Windows). They may work differently in default configurations.
In fact, #include should be like #include , except that math.h should move all its function names and such into the std:: namespace. If this isn’t happening in your Linux C++ system, there’s a problem. Unfortunately, you haven’t provided nearly enough information to figure out what’s happening.
Math library linking error in CLion on Linux [duplicate]
To do my homework I need #include «math.h» , but after updating GCC and CMake, CLion can’t link my project files. What should I do to fix this problem? In Settings -> Build, Execution and Deployment -> Toolchains CLion says that CMake version is 3.15.3 and GDB version is 8.3 and it’s OK. I already tired to reinstall GCC, CMake and CLion, but it didn’t work. Also I tired to search some info on StackOverflow, but still nothing works. Main.c:
#include #include int main() < FILE *output; output = fopen("/home/vadimsam/CLionProjects/untitled/data.txt", "w"); double x=0.,v=0.,t=0.,m=0.,k=0.,dt = 1e-5,xn,vn; while (t < 1e1) < vn = -x*sqrt((k/m))*cos(sqrt((k/m))*t)+v*cos(sqrt((k/m))*t); xn = -x*cos(sqrt((k/m))*t)+(v/sqrt((k/m)))*sin(sqrt((k/m))*t); t += dt; x = xn; v = vn; fprintf(output, "%lf %lf %lf\n", t, x, v); >fclose(output); return 0; >
cmake_minimum_required(VERSION 3.15) project(untitled2 C) set(CMAKE_C_STANDARD 11) add_executable(untitled2 main.c)
====================[ Build | untitled2 | Debug ]=============================== /home/vadimsam/.local/share/JetBrains/Toolbox/apps/CLion/ch-0/193.5096.27/bin/cmake/linux/bin/cmake --build /home/vadimsam/CLionProjects/untitled2/cmake-build-debug --target untitled2 -- -j 8 Scanning dependencies of target untitled2 [ 50%] Building C object CMakeFiles/untitled2.dir/main.c.o [100%] Linking C executable untitled2 CMakeFiles/untitled2.dir/main.c.o: In function `main': /home/vadimsam/CLionProjects/untitled2/main.c:10: undefined reference to `sqrt' /home/vadimsam/CLionProjects/untitled2/main.c:10: undefined reference to `sqrt' /home/vadimsam/CLionProjects/untitled2/main.c:10: undefined reference to `cos' /home/vadimsam/CLionProjects/untitled2/main.c:10: undefined reference to `sqrt' /home/vadimsam/CLionProjects/untitled2/main.c:10: undefined reference to `cos' /home/vadimsam/CLionProjects/untitled2/main.c:11: undefined reference to `sqrt' /home/vadimsam/CLionProjects/untitled2/main.c:11: undefined reference to `cos' /home/vadimsam/CLionProjects/untitled2/main.c:11: undefined reference to `sqrt' /home/vadimsam/CLionProjects/untitled2/main.c:11: undefined reference to `sqrt' /home/vadimsam/CLionProjects/untitled2/main.c:11: undefined reference to `sin' collect2: error: ld returned 1 exit status CMakeFiles/untitled2.dir/build.make:83: recipe for target 'untitled2' failed make[3]: *** [untitled2] Error 1 CMakeFiles/Makefile2:75: recipe for target 'CMakeFiles/untitled2.dir/all' failed make[2]: *** [CMakeFiles/untitled2.dir/all] Error 2 CMakeFiles/Makefile2:82: recipe for target 'CMakeFiles/untitled2.dir/rule' failed make[1]: *** [CMakeFiles/untitled2.dir/rule] Error 2 Makefile:118: recipe for target 'untitled2' failed make: *** [untitled2] Error 2
How to include math.h #include on kernel source file?
You cannot use the C library in a kernel module, this is even more true for the math library part.
You can’t include a userspace C module in kernel space. Also are you sure that you want to be doing this? This thread may help http://kerneltrap.org/node/16570. You can do math functions inside the kernel, just search around on http://lxr.linux.no/ for the function you need.
Standard libraries are not available in the kernel. This includes libc, libm, etc. Although some of the functions in those libraries are implemented in kernel space, some are not. Without knowing what you’re trying to call, it’s impossible to say for sure whether or not you should be doing what you’re trying to do in kernel space.
I should further note that the kernel does NOT have access to the FPU. This is to save time when switching tasks (since saving the FPU registers would add unnecessary overhead when performing context switches). You can get access to the FPU from kernel space if you really want it, but you need to be really careful not to trash the user space’s FPU registers when doing so.
Edit: This summarizes the caveat about the FPU much better than I did.
Floating point operations is not supported in the kernel. This is because when switching from kernel context to user context, registers must be saved. If the kernel would make use of floating point, then also the floating point registers would have to be saved also, which would cause bad performance for each context switch. So because floating point is very rarely needed, especially in the kernel it is not supported.
- maybe you could compile your own kernel with floating point support
- you could block context switch within your floating point operations
- the best would be to use fixed point arithmetics.
AFAIK kernel space is separated from user space, and so should the source code. /usr/include is for general programming.
This suggests that doing floating point math in the kernel is not as simple is in user-space code. Another instance suggesting that this is hard.
Still looking for a more definitive answer.
well you cannot, you can rewrite functions you need in your module, it’s dirty but it should work.
Thanks a lot for your comments
Is it possiable to make a plane C application and pass variables from kernel source file. So the C Application will compute the variables and sends back the information .
Kernel source file (kernel space) —> C Application (user space)
Kernel source file
So we may include header file in kernel source code. In case of any event, it pass the values to a C application (user space)
Details: I am trying to modify my HID joystick events(absolute x, y) So It may only move to the improved location, which will be genarated by my application, with some math functions like (pow, tan,etc).
So I used hid-input.c to get raw events, and modify them. which will be used for input subsystem through hid kernel module –
Looking for your comments
My initial reaction: don’t do that. Can you? Probably. But the divide between kernel space and user space is there for a damn good reason. There’s no guarantee that by the time the kernel finishes doing what it needs to do that your application will be running, or even be alive. I think we need more detail about what you’re trying to do. Also, unrelated: StackOverflow isn’t a forum. if you need to add information to your question, please edit your original question.
Can’t you just make your changes in your user-space application? I.e. if you get an event which moves to a bad location, you detect it in user-space?
You cannot (often, without lots of kernel know-how to lock and preserve these registers while not impacting other critical sections) use floating point registers in the kernel, and besides it is of course inappropriate to do «processing» in the kernel. Many others have mentioned this. Performance will be terrible. Thus, math.h is not provided for kernel modules. We accept this and move on.
However, as I am also a victim of crazy requirements and completely insane designs forced on us by others, this is a legitimate question. After reducing the usage of the math.h API to minimize the performance impact, you can use floating point emulation (soft-float) via correct compiler settings to implement your required functions without using floating point registers. Kernel code should already compile with these soft-float settings.
In order to implement math.h functionality, you can look at glibc or uClibc and perhaps others. Both of these libraries have generic «C» implementations of libm which implement math.h without the use of special intrinsics or platform specific types and should therefore compile just fine in the kernel.
uClibc: The above link takes you directly to the libm section of uClibc.
glibc: After «git»-ing glibc, you’ll find what you’re looking for in glibc/sysdeps/ieee754/flt-32.
glibc may be more difficult to understand because it is more sophisticated and has more inter-dependencies within itself, but uClibc only provides (at the moment) C89 math.h. If you want single precision (read: faster) or complex math functionality as in C99+, you’ll have to look at glibc.
gcc will not properly include math.h
The problem is coming from the linker, ld , rather than gcc (hence the exit status message). In general ld requires objects and libraries to be specified in the order user supplier , where user is an object that uses a library function and supplier is the object which provides it.
When your test.c is compiled to an object the compiler states that fmod is an undefined reference
$ gcc -c test.c $ nm test.o U fmod 0000000000000000 T main
(nm lists all the functions referred to by an object file)
The linker changes the undefined references to defined ones, looking up the references to see if they are supplied in other files.
$ gcc -lm test.o $ nm a.out 0000000000600e30 d _DYNAMIC 0000000000600fe8 d _GLOBAL_OFFSET_TABLE_ 00000000004006a8 R _IO_stdin_used w _Jv_RegisterClasses 0000000000600e10 d __CTOR_END__ . 0000000000601018 D __dso_handle w __gmon_start__ . U __libc_start_main@@GLIBC_2.2.5 0000000000601020 A _edata 0000000000601030 A _end 0000000000400698 T _fini 0000000000400448 T _init 0000000000400490 T _start 00000000004004bc t call_gmon_start 0000000000601020 b completed.7382 0000000000601010 W data_start 0000000000601028 b dtor_idx.7384 U fmod@@GLIBC_2.2.5 0000000000400550 t frame_dummy 0000000000400574 T main
Most of these refer to libc functions that are run before and after main to set the environment up. You can see that fmod now points to glibc, where it will be resolved by the shared library system.
My system is set up to use shared libraries by default. If I instead force static linking I get the order dependency you see
$ gcc -static -lm test.o test.o: In function `main': test.c:(.text+0x40): undefined reference to `fmod' collect2: ld returned 1 exit status
Putting -lm later in the linker command, after test.o , allows it to link successfully. Checking the symbols fmod should now be resolved to an actual address, and indeed it is
$ gcc -static test.o -lm $ nm a.out | grep fmod 0000000000400480 T __fmod 0000000000402b80 T __ieee754_fmod 0000000000400480 W fmod