Weird things happened when programming in c++20 with fmodules-ts - c++

I have two source files: main.cxx and env.cxx. And main.cxx depends on env.cxx
If I compile them with
c++ -fmodules-ts -std=c++20 -Wall -g env.cxx main.cxx, then everything works well.
But if I compile them with
c++ -fmodules-ts -std=c++20 -Wall -g -c env.cxx
c++ -fmodules-ts -std=c++20 -Wall -g -c main.cxx
c++ -fmodules-ts -std=c++20 -Wall -g env.o main.o
I get segmentation fault.
I do not know whether it is a gcc bug or not, because it works well again if I rewrite them in c++17 style, removing the module declarations.
My compiler is gcc 11.1.0 (The newest version up to now)
Here is env.cxx:
module;
#include <cstdlib>
#include <string>
#include <string_view>
#include <stdexcept>
export module env;
export namespace env
{
std::string get_env(const char* name)
{
char* p = ::getenv(name);
if (p == nullptr)
throw std::runtime_error("environment variable not found");
return std::string(p);
}
// These two functions are useless this time.
std::string get_env(const std::string& name)
{
return get_env(name.data());
}
std::string get_env(std::string_view name)
{
std::string s{name};
return get_env(s.data());
}
}
And main.cxx
module;
#include <iostream>
#include <fstream>
import env;
export module main;
int main(int argc, char** argv)
{
std::cout << env::get_env("HOME") << std::endl;
return 0;
}
Can you reproduce this?
Update 2021.06-19 15:44
In fact the two compiling commands above both work well, and the way that produces segfault is actually:
c++ -fmodules-ts -std=c++20 -Wall -g -c env.cxx
c++ -fmodules-ts -std=c++20 -Wall -g -c main.cxx
c++ -fmodules-ts -std=c++20 -Wall -g main.o env.o
Note that the place of main.o and env.o has been changed.

Related

Can't use std::filesystem in code built with make and g++

I have some problems with building my c++ app with make.
I have such c++ code:
#include <string>
#include <iostream>
#include <filesystem>
using namespace std;
namespace fs = std::filesystem;
int main()
{
auto iter = fs::directory_iterator(fs::current_path());
while(iter._At_end())
{
cout << iter->path() << endl;
}
return 0;
}
I am trying to compile object file with command:
g++-9 -std=c++17 -Wall -Wextra -pthread -lstdc++fs -c -o main.o main.cpp
But I have this error:
main.cpp:12:16: error: ‘class std::filesystem::__cxx11::directory_iterator’ has no member named ‘_At_end’
12 | while(iter._At_end())
| ^~~~~~~
So, I cant use members of classes of std::filesystem namespace but if I wanna use only class(for example std::filesystem::path), so everything is ok.
Versions of soft:
g++-9 (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
GNU Make 4.2.1
Hope you'll help me.
Just don't use _At_end() and everything will be ok.

Segmentation fault on icpc-compiled program

I am having problems understanding the segmentation fault I receive when trying to run icpc-compiled programs.
A simple example consists of the following files:
// Filename: include/lib1.h
#include <string>
namespace Lib1 {
// Template initialization, T: int, double
template< typename T>
T function1( T x, T y );
// Give me the version
std::string VERSION(void);
}
// Filename: include/lib2.h
#include <string>
namespace Lib2 {
// Give me the version
std::string VERSION(void);
}
// Filename: src/main.cpp
#include <iostream>
#include <string>
#include "lib1.h"
#include "lib2.h"
int main( int argc, char* argv[] ) {
std::cout << "Lib1::VERSION() :" << Lib1::VERSION()
<< std::endl;
std::cout << "Lib2::VERSION() :" << Lib2::VERSION()
<< std::endl;
double x = 1., y = 2.;
std::cout << "Lib1::function1(x, y): "
<< Lib1::function1(x, y)
<< std::endl;
return 0;
}
// Filename: src/lib1/lib1.cpp
#include <string>
#include "lib1.h"
template< typename T >
T Lib1::function1( T x, T y ) {
return x * y;
}
std::string Lib1::VERSION(void) {
return std::string("v0.0.2");
}
// Instantiation for dynamic library
template double Lib1::function1(double, double);
template int Lib1::function1(int, int);
// Filename: src/lib2/lib2.cpp
#include <string>
#include "lib2.h"
std::string Lib2::VERSION(void) {
return std::string("v0.0.1");
}
In this simple, stupid example, when I compile the files using
clang++ -Wall -c -fPIC -I include -o liblib1.o src/lib1/lib1.cpp
clang++ -Wall -shared -o liblib1.so liblib1.o
clang++ -Wall -c -fPIC -I include -o liblib2.o src/lib2/lib2.cpp
clang++ -Wall -shared -o liblib2.so liblib2.o
clang++ -Wall -o main.out -I include -L ./ -llib1 -llib2 src/main.cpp
the program runs fine (provided that I modify my LD_LIBRARY_PATH environment variable properly. However, when I use
icpc -Wall -c -fPIC -I include -o liblib1.o src/lib1/lib1.cpp
icpc -Wall -shared -o liblib1.so liblib1.o
icpc -Wall -c -fPIC -I include -o liblib2.o src/lib2/lib2.cpp
icpc -Wall -shared -o liblib2.so liblib2.o
icpc -Wall -o main.out -I include -L ./ -llib1 -llib2 src/main.cpp
then the program gives me:
[1] 27397 segmentation fault (core dumped) LD_LIBRARY_PATH=./:$LD_LIBRARY_PATH ./main.out
I would appreciate if you helped me understand and solve this problem. When I did some research on the web, I came across some sources talking about memory access problems and such, but I am not doing anything fancy right now. Moreover, I tried using ddd (I am not fluent/good in gdb) and running the program there, but the program exists with the segfault immidiately after the program start. I cannot even trace the program (yes, prior to running ddd, I used -debug -g switches).
It happened to be the case that Intel Parallel Studio v16.0.3 has (known) issues for Ubuntu and Arch Linux platforms, and unfortunately these systems are not officially supported, either.
One fast workaround seems to be to downgrade to v16.0.2 for now.

calling c++ function from c

I need to access a C++ function from C but I get some error like :-
/tmp/ccUqcSZT.o: In function `main':
main.c:(.text+0x5): undefined reference to `load_alert_to_db'
collect2: error: ld returned 1 exit status
My main.c code is:-
#include <stdio.h>
extern void load_alert_to_db(void);
int main(void){
/* Create empty queue */
load_alert_to_db();
return 0;
}
C++ code implementation db_manager.cpp is:-
#include <sstream>
#include <iostream>
#include <sstream>
#include <string>
#include <ctime>
#include <cstdlib>
#include <algorithm>
#include <time.h>
#include <cstring>
#include <fstream>
//using namespace oracle::occi;
#include <iostream>
using namespace std;
extern "C" void load_alert_to_db(void)
{
cout<<"db occi"<<endl;
}
makefile is:-
CC= g++
all:
$(CC) -c -Wall -Werror -fPIC db_manager.cpp
$(CC) -shared -o libdb_manager.so db_manager.o
gcc -L/home/oracle/Desktop/storage/ -Wall main.c -o data -ldb_manager
gcc -o data main.c
clean:
rm -f *.o data
so please help me which one is my problem. I am also include
export LD_LIBRARY_PATH=/home/oracle/Desktop/storage/:$LD_LIBRARY_PATH
environmental variable in .bash_profile
gcc -o data main.c
Not sure why you have this line in your makefile since it will compile main.c without reference to the previously created library and hence cause an undefined-symbol error such as the one you're seeing.
This is especially so, since you appear to have done it the right way on the preceding line:
gcc -L/home/oracle/Desktop/storage/ -Wall main.c -o data -ldb_manager
However, the entire point of using makefiles is so that it figures out the minimum necessary commands for you, based on dependencies. Lumping a large swathe of commands into a single rule tends to defeat that purpose. You would be better off making your rules a little more targeted, such as (untested but should be close):
all: data
data: main.o libdb_manager.so
gcc -o data main.o -ldb_manager
main.o: main.c
gcc -o main.o main.c
libdb_manager.so: db_manager.cpp
g++ -c -Wall -Werror -fPIC -o db_manager.o db_manager.cpp
g++ -shared -o libdb_manager.so db_manager.o
That way, if you make a small change to one part (like main.c), it doesn't have to go and compile/link everything in your build tree.
Your makefile seems to be completely broken and random, and you're not even linking the required object files. You can simplify this:
all:
$(CC) -c -Wall -Werror -fPIC db_manager.cpp
$(CC) -shared -o libdb_manager.so db_manager.o
gcc -L/home/oracle/Desktop/storage/ -Wall main.c -o data -ldb_manager
gcc -o data main.c
to just this:
all:
gcc -Wall -c main.c
g++ -Wall -c db_manager.cpp
g++ main.o db_manager.o -o data
this is what I needed to do:
Supposing the C++ function is called Debug::Write(str)
Then in your hpp file do the following:
#ifdef __cplusplus
extern "C" void DebugTmp(char *str);
#endif
Then in the corresponding cpp file do this:
void DebugTmp(char *str)
{
Debug::Write(str);
}
Then in your C file where you call DebugTmp define the prototype:
void DebugTmp(char *str);
then call it as below:
static void MyFunction( void )
{
DebugTmp("This is debug trace\n");
}

resolved: c++ : put normal method definition into source file while the templates method in header file

Since the definition of template must be put in header file, so I don't like it if the template class is big. so I want to make a normal class with some templated methods. Putting the defintion of templated method into header file, for others, put them into c++ source files. So here is what I am thinking.
// lambda.h
#include <iostream>
class X {
public:
std::function<bool(int)> filter;
template <class F>
void setFilter(F fn) {
filter = fn;
}
void big_function(int x);
};
// cat lambda.cpp
#include <iostream>
#include "lambda.h"
void X::big_function(int x) {
if (filter(x)) std::cout << x << std::endl;
}
// main2.cpp
#include <stdlib.h>
#include "lambda.h"
class Filter {
public:
bool operator()(int x) { return true; }
};
int main() {
X x;
x.setFilter(Filter());
x.big_function(3);
return 0;
}
// cat 2.sh
g++ -c lambda.cpp -ggdb
g++ -c main2.cpp -ggdb -std=c++11
g++ -o main2 main2.o lambda.o -ggdb
this program can compile, but got segment fault during executing (x.big_function(3));
#update
Q1: is my thinking is reasonable? is there any obvious error in my code?
Answer: Yes, it is reasonable, and no obvious error. Thanks to the first 4 comments, I did more test and works.
Q2: actually if I compile with -std=c++11, I will got segment fault. but no segment fault if I don't use std=c++11. ( I tried c++11 yesterday because I used lambda expression rather than function object for "Filter" at beginning). And it my real case, I can't discard c++11 features.
Answer: shame about my fault. fixed the issue by adding -std=c++11 for every compile unit.
zhifan$ sh -x 2.sh
+ g++ -c lambda.cpp -ggdb
+ g++ -c main2.cpp -ggdb
+ g++ -o main2 main2.o lambda.o -ggdb
zhifan$ ./main2
3
zhifan$ vim 2.sh
hifan$ sh -x 2.sh
+ g++ -c lambda.cpp -ggdb **-std=c++11**
+ g++ -c main2.cpp -ggdb -std=c++11
+ g++ -o main2 main2.o lambda.o -ggdb
zhifan$ ./main2
Segmentation fault: 11
zhifan$ g++ -v
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin13.4.0
Thread model: posix

error: 'mutex' in namespace 'std' does not name a type in gcc 4.6.2 [duplicate]

This question already has answers here:
C++ mutex in namespace std does not name a type
(10 answers)
Closed 9 years ago.
Simple program like this
#include <iostream> // std::cout
#include <thread> // std::thread
#include <mutex> // std::mutex
std::mutex mtx; // mutex for critical section
int main ()
{
return 0;
}
Tried the following to compile
$ /usr/local/Cellar/gcc46/4.6.4/bin/g++-4.6 -std=gnu++0x -I/usr/local/Cellar/gcc46/4.6.4/gcc/include/c++ -L/usr/local/Cellar/gcc46/4.6.4/gcc/lib temp_mutex.cpp
temp_mutex.cpp:6:1: error: 'mutex' in namespace 'std' does not name a type
By the way I am compiling on Mac.
It worked for me:
$ g++-4.7 -O2 -Wall -std=c++11 -c mutextest.cc
$ g++-4.6 -O2 -Wall -std=c++0x -c mutextest.cc
$ g++-4.6 -O2 -Wall -std=gnu++0x -c mutextest.cc
$ g++-4.4 -O2 -Wall -std=c++0x -c mutextest.cc
$ g++-4.4 -O2 -Wall -std=gnu++0x -c mutextest.cc
None of these generated any error messages.