Segmentation fault (core dumped) - dont know why - c++

I am on my way to learn C++. Im now trying to link a Library on Runtime. Im getting a segmentation fault error. I dont know why it happens.
Here is the cpp file where the error happens:
#include "CreateShape.h"
#include <dlfcn.h>
#include <iostream>
#include <sstream>
#include "Shape.h"
namespace six
{
typedef six::Shape* (*GET_OBJECT);
Shape* create_shape(const char* name)
{
Shape* shape = nullptr;
std::stringstream libName;
libName << "./lib" << name << ".so";
void* handle = dlopen(libName.str().c_str(), RTLD_LAZY);
if(handle == nullptr)
{
std::cout << "Could not open the library" << std::endl;
std::cout << "dlerror: "<< std::endl << dlerror() << std::endl;
exit(EXIT_FAILURE);
}
GET_OBJECT createShape = reinterpret_cast<GET_OBJECT>(dlsym(handle, "getNewShape"));
if(createShape == nullptr)
{
std::cout << "Could not find symbol getNewShape" << std::endl;
std::cout << "dlerror=" << dlerror() << std::endl;
dlclose(handle);
exit(EXIT_FAILURE);
}
return create_shape(name);
}
}

A stripped down version of your function is
Shape* create_shape(const char* name)
{
if(some_condition)
{
exit(EXIT_FAILURE);
}
if(some_other_condition)
{
exit(EXIT_FAILURE);
}
return create_shape(name);
}
Probably you wanted to return shape or some Shape that you created inside that function. What you do instead is calling the function recursively. The only way to stop recursion is when you hit one of the conditions and then call exit.
Though, i have to admit, why the symptom is a segfault I do not really understand.

You are not using the dl-calls the proper way. From the linux dlopen(3) man page
dlsym()
[...]Since the value of the symbol could actually be NULL (so that a NULL return from dlsym() need not indicate an error), the correct way to test for an error is to call dlerror() to clear any old error conditions, then call dlsym(), and then call dlerror() again, saving its return value into a variable, and check whether this saved value is not NULL.

Related

C++ 17 copy and delete files with special characters in their names on Windows 7 x64?

I wrote a program that copy a file from a given path(s) to another. It runs well until it meets special character in directory names or in file names. At that moment it stops and throws the error that "No such file or directory".
This is what I done until now:
#include <iostream>
#include <vector>
#include <filesystem>
#include <cxxabi.h>
#include <string>
#include <sstream>
#include <memory>
#include <windows.h>
#include <chrono>
#include <thread>
using namespace std;
namespace fs = std::filesystem;
int main(int argc, char **argv) {
vector<string> args(argv + 1, argv + argc);
auto target = args[args.size() - 1];
fs::path path = target;
cout << "Destination path: " << target << endl;
args.erase(args.end());
for (const auto &source : args) {
try {
for (const auto &entry : fs::recursive_directory_iterator(source)) {
std::string new_path = target + "\\" + entry.path().relative_path().string();
//if entry is directory:
while (true) {
if (GetDriveType(const_cast<char *>(path.root_path().string().c_str())) != DRIVE_NO_ROOT_DIR) {
if (fs::is_directory(entry)) {
//only if it NOT exists:
if (!fs::exists(new_path)) {
//create it only if not empty:
if (!fs::is_empty(entry)) {
//Creating directory tree structure with empty folders:
try {
fs::create_directories(new_path);
} catch (const std::exception &e) // caught by reference to base
{
std::cout << "When trying to create directory" << new_path
<< "A standard exception was caught, with message '"
<< e.what() << "'\n";
}
}
}
}
break;
} else {
cout << "Destination path is not available. Sleeping for 3 minutes!" << endl;
std::this_thread::sleep_for(180000ms);
}
}
while (true) {
if (GetDriveType(const_cast<char *>(path.root_path().string().c_str())) != DRIVE_NO_ROOT_DIR) {
if ((fs::is_regular_file(entry)) && (fs::exists(entry))) {
if (!fs::is_empty(entry)) {
if (!fs::exists(new_path)) {
//file does NOT exists in new path:
try {
fs::copy_file(entry.path().string(), new_path);
cout << "Copy file: " << entry.path().string() << endl;
fs::remove(entry);
} catch (const std::exception &e) // caught by reference to base
{
std::cout
<< "When trying to get file size and source a standard exception was caught, with message '"
<< e.what() << "'\n";
}
} else {
//if it exists in new path:
//first try to get file size and if this gives an error then do not copy:
if (fs::file_size(entry.path().string()) >
fs::file_size(entry.path().string())) {
try {
fs::copy_file(entry.path().string(), new_path);
cout << "Replacing file: " << entry.path().string() << endl;
fs::remove(entry);
} catch (const std::exception &e) // caught by reference to base
{
std::cout
<< "When trying to get file size and source a standard exception was caught, with message '"
<< e.what() << "'\n";
}
}
}
}
}
break;
} else {
cout << "Destination path is not available. Sleeping for 3 minutes!" << endl;
std::this_thread::sleep_for(180000ms);
}
}//end while!
}
} catch (const std::exception &e) // caught by reference to base
{
std::cout << "When recursive through directory tree a standard exception was caught, with message '"
<< e.what() << "'\n";
}
}
return 0;
}
After searching on Google and mostly on stackoverflow for a solution conclusion is that none works.
I tried adding #define UNICODE and #define _UNICODE at the top of it but it gives even more errors.
I also added -municode flag in CMakeLists in CLion but also not working (it compiles but gives runtime error).
Also tried to replace all possible string to wstring or wchar_t * with L"where possible" and to convert this entry.path().relative_path().string() to entry.path().relative_path().wstring() and also cout to wcout. Still not working.
Also changed main to wmain( int argc, wchar_t *argv[ ]) or to wmain( int argc, wchar_t *argv[ ], wchar_t *envp[ ] ) and still not working.
Also added setlocale(LC_ALL, ""); after the main function as the other article on stackoverflow says and still no improvement.
I am asking for help because I didn't find a solution for this problem and also, more of the other solution are for printing special unicode characters to console but I need more to work with them (read files names and paths that contain special unicode characters) instead of printing them.
More than this, after I tried all of these possible not working solutions I am talking about above and reverted my program back to the original code that I just posted above now it is not working at all. It says "no such file or directory" even for normal latin characters and doesn't copy or delete anything at all anymore.
Go to the header file in which std::filesystem::path is defined.
(possibly in: PATH_TO_MINGW/usr/include/c++/YOUR_VERSION/bits/fs_path)
Look for using value_type =
Look for compiler macros that define which value_type is ultimately used.
an example from the version from my system:
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
using value_type = wchar_t;
static constexpr value_type preferred_separator = L'\\';
#else
When the macro _GLIBCXX_FILESYSTEM_IS_WINDOWS is set to 1 then a wchar_t will be used, which should solve your issue.

How to terminate an application when an error happnes?

I am using a Graphics Library called Irrlicht
at some point i have to write this code
if(!device){
//error code here`
}
i am not in the main function but want to close the application when this error happens
please keep in mind that I am a beginner so this question might sound dumb
i see some people do this:
int main(){
if(!device){
return 1;
}
return 0;
}
i am not in the main function and want to exit the application outside of the main function
The following example give you an idea about some of the possibilities.
You can simply copy and paste it and play around with it. Simply use only one line of the "termination actions" like throw or exit. If you don't have the try catch block in the main function, your application will also terminate because the exception will not be caught.
struct DeviceNotAvailable {};
struct SomeOtherError{};
void func()
{
void* device = nullptr; // only for debug
if (!device)
{
// use only ONE of the following lines:
throw( DeviceNotAvailable{} );
//throw( SomeOtherError{} );
//abort();
//exit(-1);
}
}
int main()
{
// if you remove the try and catch, your app will terminate if you
// throw somewhere
try
{
func();
}
catch(DeviceNotAvailable)
{
std::cerr << "No device available" << std::endl;
}
catch(SomeOtherError)
{
std::cerr << "Some other error" << std::endl;
}
std::cout << "normal termination" << std::endl;
}

Function pointer obtained from GetProcAddress crashes the program if it uses the stdlib

I'm trying to dynamically load a dll and call a function from it at runtime. I have succeeded in getting a working pointer with GetProcAddress, but the program crashes if the function from the dll uses the stdlib. Here's the code from the executable that loads the dll:
#include <iostream>
#include <windows.h>
typedef int (*myFunc_t)(int);
int main(void) {
using namespace std;
HINSTANCE dll = LoadLibrary("demo.dll");
if (!dll) {
cerr << "Could not load dll 'demo.dll'" << endl;
return 1;
}
myFunc_t myFunc = (myFunc_t) GetProcAddress(dll, "myFunc");
if (!myFunc) {
FreeLibrary(dll);
cerr << "Could not find function 'myFunc'" << endl;
return 1;
}
cout << "Successfully loaded myFunc!" << endl;
cout << myFunc(3) << endl;
cout << myFunc(7) << endl;
cout << myFunc(42) << endl;
cout << "Successfully called myFunc!" << endl;
FreeLibrary(dll);
return 0;
}
Here's code for the dll that actually works:
#include <iostream>
extern "C" {
__declspec(dllexport) int myFunc(int demo) {
//std::cout << "myFunc(" << demo << ")" << std::endl;
return demo * demo;
}
}
int main(void) {
return 0;
}
(Note that the main method in the dll code is just to appease the compiler)
If I uncomment the line with std::cout however, then the program crashes after the cout << "Sucessfully loaded myFunc!" << endl; line but before anything else gets printed. I know there must be some way to do what I want; what do I need to change for it to work?
As discussed in the comments, it turns out that the compiler's demands for a main function were hints that I was inadvertently making a an exe that decptively used the file extension dll, not an actual dll (because I didn't quite understand the compiler options I was using), which in some way messed up the dynamic loading of that assembly.

c++ - _mkdir giving false errors windows

Hi I am trying to make a directory in windows with this code
header
#include <direct.h>
script
int main() {
string local = "C:/Program Files (x86)/Mail";
try
{
_mkdir (local.c_str ());
cout << "It is made?";
}
catch(invalid_argument& e)
{
cout << e.what () << " " << (char*) EEXIST;
if (e.what () == (char*) EEXIST) {
cout << e.what () << " " << (char*) EEXIST;
}
return;
}
}
The file is clearly not made, but it is also not making the error it should.
_mkdir won't throw an exception. (This is not python or boost, or any smart middleware)
Read the documentation you were referring to: it returns a value. 0 is OK, -1: error, ask why to errno
Don't ignore the return value. You probably have insufficient rights without UAC elevation to create the directory.
So I finally figured errno out, which for errno you need the <errno.h> header. The complete list of errno codes.
If you want to see what errno code something is throwing lets say
if (
_mkdir(((string)"C:/Program Files (x86)/Mail").c_str()) == 0 ||
errno == 17 /* this is the code for - File exists - */
){
// Do stuff
} else {
int errorCode = errno; // You need to save the code before anything else,
// because something else might change its value
cout << errorCode;
}

Usage of dlsym()/dlopen()

I wrote next program:
#include <iostream>
#include <dlfcn.h>
int main(int argc, char** argv)
{
typedef void* (*fptr)();
fptr func;
void *handle = dlopen(0, RTLD_NOW);
std::cout << dlerror() << std::endl;
*(void **)(&func) = dlsym(handle, "__libc_start_main");
std::cout << dlerror() << std::endl;
std::cout << handle << " " << func << "\n";
dlclose(handle);
return 0;
}
and try to compile in next way:
g++ -rdynamic main.cpp -ldl -o test
When I run this program I don’t see any message. Why?
Thank U for attention.
Your process is faulting because dlerror() is only valid to call in an error condition, which you never validated actually happened prior to invocation.
From the Linux docs:
The function dlerror() returns a human readable string describing the
most recent error that occurred from dlopen(), dlsym() or dlclose()
since the last call to dlerror(). It returns NULL if no errors have
occurred since initialization or since it was last called.
In other words, your dlopen succeeded, so NULL is returned from dlerror(). That NULL is then sent as a char * to std::cout, and kerboom.
Bottom line: check your error conditions before invoking dlerror(). Try this instead:
#include <iostream>
#include <dlfcn.h>
int main(int argc, char** argv)
{
typedef void* (*fptr)();
fptr func;
void *handle = dlopen(0, RTLD_NOW);
if (handle == nullptr)
{
std::cout << dlerror() << std::endl;
exit(EXIT_FAILURE);
}
func = (fptr)dlsym(handle, "__libc_start_main");
if (!func)
{
std::cout << dlerror() << std::endl;
exit(EXIT_FAILURE);
}
std::cout << handle << " " << func << "\n";
dlclose(handle);
return 0;
}
This is (likely) undefined behavior:
std::cout << dlerror() << std::endl;
...unless dlerror is actually non-null (which it probably isn't). It should be:
char* error = dlerror();
if (error != 0)
std::cout << error << std::endl;
...or:
void *handle = dlopen(0, RTLD_NOW);
if (handle == 0)
std::cout << dlerror() << std::endl;
Also, you probably should abort if dlerror is non-null (or handle is null), because calling dlsym on an null handle is also undefined behavior.
See Why does std::cout output disappear completely after NULL is sent to it.