Signal handling in C++ - c++

Argument of type void (*)(int) is incompatible with parameter of type __sighnd64_t
Below is my simple code:
#include <iostream>
#include <string>
#include <signal.h>
#include <ctype>
#include <stdlib.h>
#include <stdio.h>
typedef struct mystrcut
{
int a;
char *b;
} mystr;
void set_string ( char **, const char * );
void my_handler(int s)
{
printf("Caught signal %d\n",s);
exit(1);
}
int main()
{
const std::string str1[] = {"hello1", "hello2"};
char str2[50];
size_t size1 = str1[1].size();
cout << size1;
memcpy (str2, str1[1].c_str(), size1);
cout << str2;
mystr *m = NULL;
m = new mystrcut;
m->a = 5;
set_string(&m->b, "hello");
cout << m->b;
delete []m->b;
// void (*prev_fn)(int);
signal (SIGINT,my_handler);
return 0;
}
void set_string ( char **a, const char *b)
{
*a = new char [strlen(b)+1];
strcpy (*a, b);
}
I am working on openvms. Can I avoid the compilation error by some kind of type casting? My compiler expects `__sighnd64_t __64_signal(int, __sighnd64_t);
Adding around the handler extern c has worked. Thanks

Signal handling is not a C++, but a C. This error is bit strange...
In such cases, try to use extern "C" around your handler (to define it as C function), as https://stackoverflow.com/users/775806/n-m said in comments. Modern <signal.h> from openvms already has extern "C" inside: http://wasd.vsm.com.au/conan/sys$common/syslib/decc$rtldef.tlb?key=SIGNAL&title=Library%20/sys$common/syslib/decc$rtldef.tlb&referer=http%3A/wasd.vsm.com.au/conan/sys$common/syshlp/helplib.hlb.
HP docs says only about C, not a C++.
Another doc says that signal handler (catcher) must be declared in C as
void func(int signo);

Related

C++ char* as a function parameter

How can I pass a char pointer (char*) to the function func()?
#include <iostream>
using namespace std;
void func(char *var)
{
cout << var;
}
int main()
{
char* test = "Hello World";
func(test);
}
The compiler says:
Initialization: const char[12] cannot be converted to char *
A string literal is a const char[N] array in read-only memory (where N is the number of characters in the literal, plus 1 for the null terminator, so in your case 11+1=12). You can't point a char* pointer (ie, a pointer to non-const data) at a string literal, as that would allow for the possibility of altering read-only data, which is undefined behavior.
Simply change your pointer type to const char* instead (ie a pointer to const data), eg.
#include <iostream>
using namespace std;
void func(const char *var)
{
cout << var;
}
int main()
{
const char* test = "Hello World";
func(test);
}
Otherwise, as you say you have no control over the function declaration, then if you really want to pass a string literal to a char* pointer, you should copy the characters into a separate writable char[] buffer first, and then point at that instead, eg:
#include <iostream>
using namespace std;
void func(char *var)
{
cout << var;
}
int main()
{
char test[] = "Hello World";
func(test);
}
Or, if you know for sure that the function will never modify the characters, you can just cast off the const-ness using const_cast (though this is highly NOT recommended, I'm including it for completeness), eg:
#include <iostream>
using namespace std;
void func(char *var)
{
cout << var;
}
int main()
{
char* test = const_cast<char*>("Hello World");
func(test);
/* alternatively:
const char* test = "Hello World";
func(const_cast<char*>(test));
*/
}
This code would print the string "Hello World"
void func(char *var)
{
for( ;*var!='\0'; var++) { //!= from null terminator
cout<<*var;
}
}
int main()
{
char test[] = "Hello World";
func(test);
return 0;
}

Returning a C string stored in a class

I am trying to print out a C string that is stored in a class by returning the value using an accessor function.
Thanks for any help!
This is the error I get when I compile:
cstringClass.cpp: In member function 'char Foo::get_name()':
cstringClass.cpp:37:9: error: invalid conversion from 'char*' to 'char' [-fpermi
ssive]
return name;
^
Here is the code:
#include <iostream>
#include <cstring>
using namespace std;
class Foo
{
public:
void set_name(char a[]);
char get_name();
private:
char name[10];
};
int main()
{
Foo bar;
char a[10] = "Test";
bar.set_name(a);
cout << bar.get_name();
return 0;
}
void Foo::set_name(char a[])
{
strcpy(name, a);
}
char Foo::get_name()
{
return name;
}
So the error says:
cstringClass.cpp: In member function 'char Foo::get_name()':
^^^^^^^^^^^^^^^^^^^^
And indeed:
char get_name();
You declared get_name as returning a single char, not a pointer to a string. You probably meant char *get_name();.
As the error message states, your get_name() function doesn't return the appropriate type, which should be char* based on the data it returns, which is name[10]. char returns only 1 byte of data and name[10] has 10. Please see the corrected code below.
#include <iostream>
#include <cstring>
using namespace std;
class Foo
{
public:
void set_name(char a[]);
char *get_name(); //<-- correction
private:
char name[10];
};
int main()
{
Foo bar;
char a[10] = "Test";
bar.set_name(a);
cout << bar.get_name();
return 0;
}
void Foo::set_name(char a[])
{
strcpy(name, a);
}
char *Foo::get_name() //<-- correction
{
return name;
}

Instance of class only allows 1 method, or program crashes

I am learning classes and OOP, so I was doing some practice programs, when I came across the weirdest bug ever while programming.
So, I have the following files, beginning by my class "pessoa", located in pessoa.h:
#pragma once
#include <string>
#include <iostream>
using namespace std;
class pessoa {
public:
//constructor (nome do aluno, data de nascimento)
pessoa(string newname="asffaf", unsigned int newdate=1996): name(newname), DataN(newdate){};
void SetName(string a); //set name
void SetBornDate(unsigned int ); //nascimento
string GetName(); //get name
unsigned int GetBornDate();
virtual void Print(){}; // print
private:
string name; //nome
unsigned int DataN; //data de nascimento
};
Whose functions are defined in pessoa.cpp
#include "pessoa.h"
string pessoa::GetName ()
{
return name;
}
void pessoa::SetName(string a)
{
name = a;
}
unsigned int pessoa::GetBornDate()
{
return DataN;
}
void pessoa::SetBornDate(unsigned int n)
{
DataN=n;
}
A function, DoArray, declared in DoArray.h, and defined in the file DoArray.cpp:
pessoa** DoArray(int n)
{
pessoa* p= new pessoa[n];
pessoa** pointer= &p;
return pointer;
}
And the main file:
#include <string>
#include <iostream>
#include "pessoa.h"
#include "DoArray.h"
#include <cstdio>
using namespace std;
int main()
{
//pessoa P[10];
//cout << P[5].GetBornDate();
pessoa** a=DoArray(5);
cerr << endl << a[0][3].GetBornDate() << endl;
cerr << endl << a[0][3].GetName() << endl;
return 0;
}
The weird find is, if I comment one of the methods above, "GetBornDate" or GetName, and run, the non-commented method will run fine and as supposed. However, if both are not commented, then the first will run and the program will crash before the 2nd method.
Sorry for the long post.
Let's look into this function:
int *get()
{
int i = 0;
return &i;
}
what is the problem with it? It is returning pointer to a local variable, which does not exist anymore when function get() terminates ie it returns dangling pointer. Now your code:
pessoa** DoArray(int n)
{
pessoa* p= new pessoa[n];
return &p;
}
do you see the problem?
To clarify even more:
typedef pessoa * pessoa_ptr;
pessoa_ptr* DoArray(int n)
{
pessoa_ptr p= whatever;
return &p;
}
you need to understand that whatever you assign to p does not change lifetime of p itself. Pointer is the same variable as others.

Simple reflection mechanism

Is there any solution to run a function/macro that name is created by concatenation of two strings?
I just want to do something like that:
template <char *A, char *B, int C>
int function_that_run_other_function(void){
// Here is the main point
char function_name[80];
strcpy (function_name, "function");
strcat (function_name, A);
strcat (function_name, B);
return function_name(C);
}
I can do this using macro:
#define macro_that_run_function(A,B,C) \
function_##A##B##(C);
But I don't want to use macro because of many problems with macros.
Is it possible to do in C++ without any additional libraries?
I got curious and after a little while I ended up with this ungodly mess and general mainentace nightmare:
main.cpp:
#include <map>
#include <iostream>
#include <sstream>
#include <functional>
#include <cstring>
typedef std::function<void(int)> func;
typedef std::map<std::string, func> FuncMap;
template <char* A, char* B, int C>
void runner(FuncMap funcs){
std::stringstream ss;
ss <<A <<B;
return funcs[ss.str()](C);
}
void ABC(int val) {
std::cout <<"Woo: " <<val <<"\n";
}
extern char a[]; //due to external linkage requirement
extern char b[];
int main(...) {
FuncMap funcs;
strcpy(a, "A");
strcpy(b, "B");
funcs["AB"] = std::bind(&ABC, std::placeholders::_1);
runner<a, b, 0>(funcs);
return 0;
}
vars.cpp:
char a[5] = {""};
char b[5] = {""};
So yes with enough force you can make c++ do something along the lines of what you want, but I really wouldn't recommend it.
No, C++ does not allow the compile or run time manipulation or inspection of symbol names (barring the implementation specified type info stuff).
Dynamic libraries often export names (mangled for C++, almost unmangled for `extern "C"``), and libraries for loading them usually (always?) allow them to be loaded by string value.

Cast (void *) to any other in a safe way

Is this safe now?
#include <stdio.h>
#include <string.h>
long lee( void *v1)
{
long i1;
memcpy(&i1,v1,sizeof(long));
return i1;
}
//Added conversion to double:
double lee_d( void *v1)
{
double i1;
memcpy(&i1,v1,sizeof(double));
return i1;
}
void main()
{
long val=1777777;
long ii;
ii=lee((void *) &val);
double dd=377e-177;
dd=lee_d((void *) &dd);
ii=ii;
}
It works well under MS studio.
I do not use this pointer translations but when using curl libraries
The integral division will happen before the adding of 0.99999 therefore you are going to get an integer, which may be 0, 1, 2, add an arbitrary 0.99999 to it which achieves nothing, then cast it back to long.
size1 could still be 0 so val[0] might not be valid.
It is also difficult to know what you are trying to achieve.
To answer your question directly, it is not safe.
As far as lee() and your call to it goes, yes it's safe.
As has been said the (void *) are unneccessary & should be avoided until you know what you're doing. In the function declaration concerned it just means the function takes a pointer to something but it doesn't matter what the type of 'something' is.
E.g.
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
static void doit(int *); // Function Prototypes. VERY IMPORTANT.
static void doitAgain(void *);
int main(int argc, char *argv[]) {
int i = 0x12345;
doit(&i);
doitAgain(&i);
}
static void doit(int *b)
{
int *foo = malloc(sizeof(int));
memcpy(foo, b, sizeof(int));
fprintf(stdout, "foo is 0x%x\n", *foo);
}
static void doitAgain(void *b)
{
int *foo = malloc(sizeof(int));
memcpy(foo, b, sizeof(int));
fprintf(stdout, "foo is 0x%x\n", *foo);
}
And when we run it:
$ make
cc main.c -o main
$ ./main
foo is 0x12345
foo is 0x12345