i am trying to make user threads in C++, so while trying to initialize them i am getting a compiler error :translate_address was not declared in this scope
#include <iostream>
#include <cstdlib>
#include <csignal>
#include <csetjmp>
#define JB_SP 6 //Location in the code
#define JB_PC 7 //Stack pointer
#define STACK_SIZE 10
typedef unsigned long address_t; //64bit address
sigjmp_buf jbuf[3];
char stack1[STACK_SIZE];
void f(){
}
void setup(){
unsigned int sp, pc;
sp = (address_t)stack1 + STACK_SIZE - sizeof(address_t);
pc = (address_t)f;
sigsetjmp(jbuf[0],1);
(jbuf[0]->__jmpbuf)[JB_SP] = translate_address(sp);
(jbuf[0]->__jmpbuf)[JB_PC] = translate_address(pc);
sigemptyset(&jbuf[0]->__saved_mask);//empty saved signal mask
}
int main(){
return 1;
}
am i meant to include it some how? or is there a different problem?
thank you.
translate_address is not a Linux function. If you're referring to some kind of book or example code, it should explain where you're supposed to get this function from. If it doesn't, chances are it's not meant for Linux (or is a really, really bad reference/example).
Furthermore, you should NOT modify the contents of jmp_buf or sigjmp_buf directly. These are architecture and platform-dependent structures, and only the C library is allowed to mess with them. Since the contents of the structures are OS-dependent, if you're using a reference intended for some other OS when modifying sigjmp_buf, Bad Things will happen.
You should instead either use setcontext, getcontext, and makecontext for user threads (fibers) or pthread_create for OS-level threads.
Related
I am a bit new to c++ and want to learn more by trying a specific project. This project is somewhat bigger project where I want to test the dependence of some numerical method "function" with respect to parameters like array size and what not. I figured the best way to organize my code would be to create
A file implementing the functions I want to use
// implement.h
#include <cmath>
struct input_params{
int input_array_size;
// other parameters
}
void function(float* , float* , input_params);
// implement.cpp
#include <cmath>
#include "implement.h"
void function(float *input, float *output, input_params args){
// do stuff
}
A config file specifying what my input_params will contain (with a corresponding header file)
#include "config.h"
input_params args;
#include "implement.h"
#include "config.h"
input_params args;
args.input_array_size = 100; // something I would change before compile time
A script that will actually run the code
#include <cmath>
#include "implement.h"
#include "config.h"
// float *input = new [arg.input_array_size];
float input[arg.input_array_size]; // I want to make this stack-allocated for performance reasons
// float *output = new [arg.output_array_size];
float output[arg.output_array_size];
function(input, output, args);
My questions are as follows:
How should I compile the code using g++?
How do compile my "config" file so that my parameters are known at compile time?
Is there a better, alternative way of actually doing this?
The simplest approach would be to make your configuration file create macros:
// config.h
#define ARG_INPUT_SIZE 100
#define ARG_OUTPUT_SIZE 300
// some_other_file.c
#include "config.h"
float input[ARG_INPUT_SIZE];
float output[ARG_OUTPUT_SIZE];
It's pretty unlikely that allocating this in the bss vs the heap is actually going to be meaningfully important to any performance metrics.
"Is there a better, alternative way of actually doing this?"
Of course there is. Just use a std::vector<float> for the input / output parameters. You can adapt the necessary size of them dynamically as needed.
If you still want fixed sizes, and do that at compile time you can use std::array<float,MY_SIZE> and define the size you want using the -D command line option of g++:
g++ -D MY_SIZE=100 ...
std::vector and std::array are a lot easier to deal with than raw c-style arrays or pointers.
Example code:
#include <array>
using inarray_t = std::array<float,MY_INPUT_SIZE>;
using outarray_t = std::array<float,MY_OUTPUT_SIZE>;
// Change the signature of your function
void function(inarray_t&, outarray_t& , input_params);
// ...
int main() {
// ...
inarray_t input; // this is stack-allocated for performance reasons
outarray_t output; // this is stack-allocated for performance reasons
// ...
}
Take care that the stack allocations don't exceed the stack size limitations, these aren't that big usually, and you can end up with stack overflow (no pun intended) very quickly.
Background: Downloaded google-coredumper-1.2.1.tar.gz from code.google.com. built the code and make install. Added library and function call to my application and execute. No core file, Logs state Operation not permitted. So I created a simple example and stepped through it and found that the library believes that the executable is already being traced. Any ideas?
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include "crashtest.h"
#include <google/coredumper.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
FILE * backtrace_file = NULL;
#define SIZE 100
void CREATE_COREDUMP()
{
printf("NOTICE, Creating a core dump for debugging\n");
char extension[64];
time_t t = time((time_t*)NULL);
tm * theTime = localtime(&t);
snprintf( extension,
sizeof(extension) - 1,
"core.crashtest_02d_%02d_%02d_%02d", (theTime->tm_mday),
(theTime->tm_hour),
(theTime->tm_min) ,
(theTime->tm_sec) );
if (WriteCoreDump(extension) != 0) {
std::string errmsg(extension);
errmsg.append(" : ");
errmsg.append(strerror(errno));
printf("WARNING, Failed to create coredump: %s\n", errmsg.c_str() );
}
}
static void mysighandler(int sig)
{
printf("ERROR, Somebody Segmentation Faulted. About to Exit\n");
CREATE_COREDUMP();
exit(0);
}
crashtest::crashtest() {
char * errcond = NULL;
memcpy(errcond, "Crash This", 10);
}
crashtest::~crashtest() {}
int main(int argc, char** argv) {
struct sigaction sa;
sa.sa_flags = SA_SIGINFO;
sigemptyset(&sa.sa_mask);
sa.sa_handler = &mysighandler;
sigaction(SIGSEGV, &sa, NULL);
crashtest ct;
return 0;
}
The point of the exercise is that the main code generates a segmentation fault occasionally which does not make sense because all the values are initialized. Therefore I am trying to discover why there is a segmentation fault and would like to get a core to track down the offending line of code. I cannot just kill since the code is required to recover and continue. That is why google-coredumper is thought to be used.
According to http://www.gossamer-threads.com/lists/linux/kernel/622686, it seems that coredumper in its current state is not usable anymore:
I believe, if I interpret the data on kernel.org correctly, this
change was made by Linus and shipped with 2.6.15.
Both perftools and coredumper need to locate all threads in the active
application in order to work. As libpthread has had changing and
poorly documented APIs to get this information, and as our intent is
to support all kernel versions and all libc versions, we resorted to
ptracing any process that is suspected to be one of our threads in
order to determine if it actually is. This has the added benefit of
finding all threads (including ones not managed by libpthread) and
of temporarily suspending them, so that we have a stable memory image
that we can inspect. Think of both tools as something like a
lightweight in-process debugger.
Obviously, special care has to be taken to not ptrace our own thread,
and to avoid any library calls that could deadlock.
Before the patch, attaching ptrace to my own threads was a valid
operation. With this new patch, I can no longer do that.
I'm having some trouble with function pointers and passing them as inputs to other functions in C++. I've written some simplified code that sums up the trouble that I'm having. I have two .cpp files as below
functions.cpp
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#define _CRT_SECURE_NO_WARNINGS
typedef double(*real_function)(double);
double one(double x) {
return double(1);
}
void applyfunction(int length, real_function f, double* result) {
int j;
result[0] = 0;
for (j = 1; j < length; j++) {
result[j] = f(result[j - 1]);
}
}
Source.cpp
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#define _CRT_SECURE_NO_WARNINGS
typedef double(*real_function)(double);
real_function one;
void applyfunction(int, real_function, double*);
int main(void) {
double* result;
result = (double*)calloc(10, sizeof(double));
applyfunction(10, one, result);
return(0);
}
When I compile this, I get the following error in Visual Studio 2015
Exception thrown at 0x00000000 in Project3.exe: 0xC0000005: Access violation executing location 0x00000000.
If there is a handler for this exception, the program may be safely continued.
What is going wrong? The funny thing is that if we define those functions one and applyfunction in the source.cpp file (i.e. put all code in a single file), things seem to work. So, I think that it must be something very simple that I am getting wrong. Thank you for any help.
real_function one;
This creates a global variable one which is initialized to a null pointer.
applyfunction(10, one, result);
You then pass that null pointer to applyfunction...
result[j] = f(result[j - 1]);
...wherein you try to call it, generating the null pointer exception.
To fix this, don't create a variable one in Source.cpp. Instead, add a prototype that matches the definition in functions.cpp. In other words, replace real_function one; with
double one(double x);
real_function one;
doesn't declare the function one in the other file; it defines a function pointer called one. Because it's global (and thus has static storage), it's initialized to null. Your program crashes because it's trying to call a null pointer.
One way to fix this is to change
typedef double(*real_function)(double);
to
typedef double real_function(double);
This way real_function actually names a function type (not a pointer).
I'm getting this super bazar bug in my code that I can't figure out. Basically what's happening is the data member 'char_string' is being created without me even assigning anything to it. It prints out "test123", when in the process.cpp file, I haven't copied the data to it yet.
main.cpp
#include <iostream>
using namespace std;
#include "process.h"
int main(){
char string[] = "test123";
w1::CString test(string);
return 0;
}
process.h
#ifndef PROCESS_H
#define PROCESS_H
namespace w1{
class CString{
private:
int num_of_chars;
char char_string[];
public:
CString(char *);
};
}
#endif
process.cpp
#include <iostream>
#include "process.h"
w1::CString::CString(char * c_string){
std::cout << char_string << std::endl;
}
OUTPUT:
test123
It is not instantiated. According to http://www.cplusplus.com/doc/tutorial/classes/,
For members of fundamental types, it makes no difference which of the
ways above the constructor is defined, because they are not
initialized by default, but for member objects (those whose type is a
class), if they are not initialized after the colon, they are
default-constructed.
Pointers (and thus arrays) are fundamental types, so they are not default constructed if uninitialized. They will point to some memory location, and using that location will result in undefined behavior. In this case you are seeing it happen to point to an actual (and relevant) memory location, but it could just as easily point to 0 (nullptr) or any other value. You might need to look in the internals of your compiler to learn why, but in general you should never depend on such undefined behavior.
Background:
I've found myself with the unenviable task of porting a C++ GNU/Linux application over to Windows. One of the things this application does is search for shared libraries on specific paths and then loads classes out of them dynamically using the posix dlopen() and dlsym() calls. We have a very good reason for doing loading this way that I will not go into here.
The Problem:
To dynamically discover symbols generated by a C++ compiler with dlsym() or GetProcAddress() they must be unmangled by using an extern "C" linkage block. For example:
#include <list>
#include <string>
using std::list;
using std::string;
extern "C" {
list<string> get_list()
{
list<string> myList;
myList.push_back("list object");
return myList;
}
}
This code is perfectly valid C++ and compiles and runs on numerous compilers on both Linux and Windows. It, however, does not compile with MSVC because "the return type is not valid C". The workaround we've come up with is to change the function to return a pointer to the list instead of the list object:
#include <list>
#include <string>
using std::list;
using std::string;
extern "C" {
list<string>* get_list()
{
list<string>* myList = new list<string>();
myList->push_back("ptr to list");
return myList;
}
}
I've been trying to find an optimal solution for the GNU/Linux loader that will either work with both the new functions and the old legacy function prototype or at least detect when the deprecated function is encountered and issue a warning. It would be unseemly for our users if the code just segfaulted when they tried to use an old library. My original idea was to set a SIGSEGV signal handler during the call to get_list (I know this is icky - I'm open to better ideas). So just to confirm that loading an old library would segfault where I thought it would I ran a library using the old function prototype (returning a list object) through the new loading code (that expects a pointer to a list) and to my surprise it just worked. The question I have is why?
The below loading code works with both function prototypes listed above. I've confirmed that it works on Fedora 12, RedHat 5.5, and RedHawk 5.1 using gcc versions 4.1.2 and 4.4.4. Compile the libraries using g++ with -shared and -fPIC and the executable needs to be linked against dl (-ldl).
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <list>
#include <string>
using std::list;
using std::string;
int main(int argc, char **argv)
{
void *handle;
list<string>* (*getList)(void);
char *error;
handle = dlopen("library path", RTLD_LAZY);
if (!handle)
{
fprintf(stderr, "%s\n", dlerror());
exit(EXIT_FAILURE);
}
dlerror();
*(void **) (&getList) = dlsym(handle, "get_list");
if ((error = dlerror()) != NULL)
{
printf("%s\n", error);
exit(EXIT_FAILURE);
}
list<string>* libList = (*getList)();
for(list<string>::iterator iter = libList->begin();
iter != libList->end(); iter++)
{
printf("\t%s\n", iter->c_str());
}
dlclose(handle);
exit(EXIT_SUCCESS);
}
As aschepler says, its because you got lucky.
As it turns out, the ABI used for gcc (and most other compilers) for both x86 and x64 returns 'large' structs (too big to fit in a register) by passing an extra 'hidden' pointer arg to the function, which uses that pointer as space to store the return value, and then returns the pointer itself. So it turns out that a function of the form
struct foo func(...)
is roughly equivlant to
struct foo *func(..., struct foo *)
where the caller is expected to allocate space for a 'foo' (probably on the stack) and pass in a pointer to it.
So it just happens that if you have a function that is expecting to be called this way (expecting to return a struct) and instead call it via a function pointer that returns a pointer, it MAY appear to work -- if the garbage bits it gets for the extra arg (random register contents left there by the caller) happen to point to somewhere writable, the called function will happily write its return value there and then return that pointer, so the called code will get back something that looks a like a valid pointer to the struct it is expecting. So the code may superficially appear to work, but its actually probably clobbering a random bit of memory that may be important later.