C++ segmentation fault when creating pthreads - c++

void createThreads(int k){
struct threadData threadData[k];
int numThreads = k;
int i = 0;
int err = 0;
pthread_t *threads = static_cast<pthread_t*>(malloc(sizeof(pthread_t) * numThreads));
for(i = 0;i<numThreads;i++){
threadData[i].thread_id = i;
threadData[i].startIndex = ((N/k)*i);
threadData[i].stopIndex = ((N/k)*(i+1));
err = pthread_create(&threads[i], NULL, foo, (void *)&threadData[i]);
if(err != 0){
printf("error creating thread\n");
}
}
}
Here, N and k are integers where the remainder of N/k is guaranteed to be 0.
including createThreads(numThreads); in main will cause my program to seg fault and commenting it out will take care of this however any printf debug statements I put into createThreads (even on the first line inside the function) will not show so I am pretty confused as to how to debug this. All help is appreciated.

I suppose the problem is that your arg parameter is on stack of your createThreads function:
struct threadData threadData[k];
so once your thread gets created and run, and createThreads returns, threadData is no longer valid, so your thread function should not touch argument data. Otherwise its undefinded behaviour and crash.
so to fix it, you should either, make threadData global (outside createThreads), or malloc it.

Related

Is it possible to send the instance of class with member function between two process?

Consider I have this kind of class in process 1. And run process2 whose code is written in completely different file.
class A{
public:
int data;
A()
int f();
}
I want to make instance a of class A in process1, send it to process2, and run a.f() in process2. I studied about IPC mechanism including POSIX shared memory or message queue and read many examples, but the most of examples only expalin how to send single data like integer, or struct without member function.
Is it possible?
If it's possible, how can I do it using POSIX shared memory? Can you give me short example?
It is definitely possible to do it in shared memory.
Take for example the following class:
struct A {
A(int initial_value) {
internal_value = initial_value;
}
void write(int value) {
internal_value = value;
}
int read() const {
return internal_value;
}
void watch(int value) {
while (internal_value == value) usleep(1000);
}
std::atomic<int> internal_value;
};
The class uses an atomic counter inside that will be shared between two processes, both reading and writing from it.
Let's first create some shared memory space for it.
int mapsize = getpagesize();
int fid = ::open("/tmp/shared.dat", O_CREAT | O_RDWR, S_IRWXU | S_IRWXG);
ftruncate(fid, mapsize);
void* ptr = ::mmap(nullptr, mapsize, PROT_READ | PROT_WRITE, MAP_SHARED, fid, 0);
Notice I am not checking the return values for brevity but you should do in your code.
Now with this memory space allocated, let's initialize an object of class "A" inside that memory with placement new.
A* a = new (ptr) A(0); // placement new
Then we fork another process to simulate the IPC mechanism working
pid_t pid = fork();
For the parent process code, we loop from 0 to 10 first waiting for it to be different from zero then 2, 4 etc. Then in the end we wait for the child to finish.
if (pid != 0) {
for (int j = 0; j < 10; j += 2) {
printf("-->parent %d\n", j);
a->watch(j);
a->write(j + 2);
}
printf("Finishing parent\n");
int status;
wait(&status);
For the child process, we write 1 and wait for 1, then write 3 and wait for 3 and so on like the parent but with odd numbers.
} else {
for (int j = 1; j < 10; j += 2) {
printf("-->child %d\n", j);
a->write(j);
a->watch(j);
}
printf("Finishing child\n");
}
In the end of both we unmap the memory and close the file
::munmap(ptr, mapsize);
::close(fid);
It prints:
-->parent 0
-->child 1
-->parent 2
-->child 3
-->parent 4
-->child 5
-->parent 6
-->child 7
-->parent 8
-->child 9
Finishing parent
Finishing child
Compiler Explorer link: https://godbolt.org/z/5orPaEhPM
If you need two independent processes running side by side you just need to be careful with how you create them, synchronize them.
Start the same way opening a file and memory mapping it
int mapsize = getpagesize();
const char* filename = "/tmp/shared.dat";
int fid = ::open(filename, O_CREAT | O_RDWR, S_IRWXU | S_IRWXG);
void* ptr = ::mmap(nullptr, mapsize, PROT_READ | PROT_WRITE, MAP_SHARED, fid, 0);
Notice that at this point if you write or read from the pointer ptr you will get a segfault.
Then you need to lock the file
while (flock(fid, LOCK_EX) != 0) {
usleep(10000); // sleep a bit
}
Then you need to check the file. If the size is zero, it is uninitialized. If the file is already initialized, you do not use placement new, you just cast the raw pointer.
A* a;
if (getfilesize(fid) == 0) {
ftruncate(fid, mapsize);
a = new (ptr) A(0);
} else {
a = reinterpret_cast<A*>(ptr);
}
After that you read your value and increment it while the file is still locked.
int value = a->read();
value += 1;
a->write(value);
Then you can unlock the file
flock(fid, LOCK_UN); // unlock
Then it's just the same drill of waiting, incrementing and looping, only a tad different.
// Change 5 times
for (int j = 0; j < 5; ++j) {
printf("-->proc %d %d\n", getpid(), value);
a->watch(value);
value += 2;
a->write(value);
}
In the end, just unmap and close as before
::munmap(ptr, mapsize);
::close(fid);
The whole code is here: https://godbolt.org/z/zK3WKWqj4
Do not to use IPC, but RPC (Remote Procedure Calls) for that. E.g. gRPC : https://grpc.io/docs/what-is-grpc/introduction/. Sharing data "manually" with shared memory can be done but you end up having to write synchronization mechanism yourself (locks on data, signals that data has been written into shared memory etc.)

C++ threads add two array to one result array [duplicate]

I'm fairly new to threads in C. For this program I need to declare a thread which I pass in a for loop thats meant to print out the printfs from the thread.
I can't seem to get it to print in correct order. Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define NUM_THREADS 16
void *thread(void *thread_id) {
int id = *((int *) thread_id);
printf("Hello from thread %d\n", id);
return NULL;
}
int main() {
pthread_t threads[NUM_THREADS];
for (int i = 0; i < NUM_THREADS; i++) {
int code = pthread_create(&threads[i], NULL, thread, &i);
if (code != 0) {
fprintf(stderr, "pthread_create failed!\n");
return EXIT_FAILURE;
}
}
return EXIT_SUCCESS;
}
//gcc -o main main.c -lpthread
That's the classic example of understanding multi-threading.
The threads are running concurrently, scheduled by OS scheduler.
There is no such thing as "correct order" when we are talking about running in parallel.
Also, there is such thing as buffers flushing for stdout output. Means, when you "printf" something, it is not promised it will happen immediately, but after reaching some buffer limit/timeout.
Also, if you want to do the work in the "correct order", means wait until the first thread finishes it's work before staring next one, consider using "join":
http://man7.org/linux/man-pages/man3/pthread_join.3.html
UPD:
passing pointer to thread_id is also incorrect in this case, as a thread may print id that doesn't belong to him (thanks Kevin)

Getting debug error in multithreaded VS code and unable to find issue

I keep getting a debug error thrown, telling me that abort() has been called and then when I go to debug in Visual Studio it takes me to the following code (the last line is where it throws):
void __cdecl _NMSG_WRITE (
int rterrnum
)
{
const wchar_t * const error_text = _GET_RTERRMSG(rterrnum);
if (error_text)
{
int msgshown = 0;
#ifdef _DEBUG
/*
* Report error.
*
* If _CRT_ERROR has _CRTDBG_REPORT_WNDW on, and user chooses
* "Retry", call the debugger.
*
* Otherwise, continue execution.
*
*/
if (rterrnum != _RT_CRNL && rterrnum != _RT_BANNER && rterrnum != _RT_CRT_NOTINIT)
{
switch (_CrtDbgReportW(_CRT_ERROR, NULL, 0, NULL, L"%s", error_text))
{
case 1: _CrtDbgBreak(); msgshown = 1; break;
It appears when I step over whatever-is-the-last-line in the below function:
X::my_func(){
//a,b,c are 2x ints and a unordered_map
std::thread t1(&X::multi_thread_func, this, a, b, c);
int c = 0;
//The debug error message doesn't appear until I step over this line. If I were
//to add further code to this function then the error only appears after stepping
//over the last line in the function.
int c1 = 0;
}
I appreciate there's not a lot to go on- but could people give me tips how I could continue my investigation from within Visual Studio 2012?
EDIT: If I remove the multithreaded call I don't get the error
A std::thread instance must either be joined or detached, before it can be destructed (what happens, as soon as t1 goes out of scope). Otherwise, the destructor of std::thread will call std::terminate(). This might be the cause of that abort.
X::my_func(){
//a,b,c are 2x ints and a unordered_map
std::thread t1(&X::multi_thread_func, this, a, b, c);
t1.join();// <--- ... however, using a thread like this makes little to no sense.
int c = 0;
//The debug error message doesn't appear until I step over this line. If I were
//to add further code to this function then the error only appears after stepping
//over the last line in the function.
int c1 = 0;
}

Accessing and modifying thread data problem in c++

I have problems to access and modify my multiple thread data. Is there are any proper way to do this?
Here is my full code:
#include <stdio.h>
#include <windows.h>
// Create thread data structure
struct data
{
int a;
float b;
char *c;
};
DWORD WINAPI threadfn(LPVOID lpParam)
{
printf("Address of thread data:\n");
for(int i=0; i<sizeof(lpParam); i++)
printf("%X\n", (int*)lpParam + i);
// Print out initial values
printf("\nInitial values:\n");
printf("a: %d\n", *((int*)lpParam));
printf("b: %.2f\n", *((float*)lpParam + 1));
printf("c: %s\n", *((int*)lpParam + 2));
// Modify thread data values
*(int*)lpParam = 200;
*((float*)lpParam + 1) = 25.80;
*((char*)lpParam + 2) = "Es la una";
return 0;
}
int main()
{
HANDLE hThread;
data thread;
// Set initial thread data values
thread.a = 10; // Integer data type
thread.b = 15.60; // Float data type
thread.c = "Que hora es?"; // String data type
hThread = CreateThread(NULL, 0, threadfn, &thread, 0, NULL);
WaitForSingleObject(hThread, INFINITE);
// Print out thread value after modification
printf("\nAfter thread modifications:\n");
printf("a: %d\n", thread.a);
printf("b: %.2f\n", thread.b);
printf("c: %s\n", thread.c);
getchar();
return 0;
}
And this is my output:
Address of thread data:
28FF20
28FF24
28FF28
28FF2C
Initial values:
a: 10
b: 15.60
c: Que hora es?
After thread modifications:
a: 7405768
b: 25.80
c: Que hora es?
As you can see, the 'c' value is same. How do i modify string value?
What on earth are you doing?! All the casting of lpData is very, very wrong. If you have to do that much casting to accomplish something, you are probably not doing it the right way.
Anyway, your code should look like this:
DWORD WINAPI threadfn(LPVOID lpParam)
{
printf("Address of thread data:\n");
data *lpData = (data *)(lpParam);
for(int i=0; i<sizeof(lpParam); i++)
printf("%X\n", (int*)lpParam + i);
// Print out initial values
printf("\nInitial values:\n");
printf("a: %d\n", lpData->a);
printf("b: %.2f\n", lpData->b);
printf("c: %s\n", lpData->c);
// Modify thread data values
lpData->a = 200;
lpData->b = 25.80;
lpData->c = "Es la una";
return 0;
}
You should be using (data *)(lpParam) because it basically reverses what's happening when you call CreateThread. Personally, think the stupid P notation for type names is more of a hinderance than a help because it obscures what's actually happening. Hungarian notation in general has this problem IMHO.
In your main function, you have this code:
hThread = CreateThread(NULL, 0, threadfn, &thread, 0, NULL);
The 4th argument to CreateThread is a void * (aka a PVOID). The type of the expression &thread is data *. This means that the data * is being implicitly converted to a void *. If you make that conversion explicit, the code looks like this:
hThread = CreateThread(NULL, 0, threadfn, (void *)(&thread), 0, NULL);
So, in order to 'undo' what was done, you need to 'reverse' the cast. You need to turn the void * back into a data *, which means than in threadfn you need the code data *lpData = (data *)(lpParam);.
Additionally, you are courting disaster by setting c to point at constant character strings since you didn't declare it as a const char *. I'm surprised the compiler isn't giving you an error. The disaster happens when you do something like data.c[0] = 'f';. When you do that you will be trying to modify memory that may very well be flagged as read-only and cause your program to crash. And that's the kindest thing that could happen.
You're not accessing your structure members properly from within the spawned thread. Consider this:
*(int*)lpParam = 200;
It means convert the lpParam to an int*, then access the integer at that address. That works fine, but:
*((float*)lpParam + 1) = 25.80;
Converts lpParam to a float*, then adds sizeof(float*) bytes to it, then dereferences it. That only works if sizeof(int) happens to be the same as sizeof(float)... which is common enough but not guaranteed.
*((char*)lpParam + 2) = "Es la una";
This is a real worry though: this considers lpParam a char*, then adds two BYTES to it, which probably positions it half way into the four bytes used by the integer member of the struct (assuming a 32 bit app), then writes over the single character at that address with a truncated value (the least significant byte/char) from the char pointer to your new string [incorporating correction thanks to Chris's comment].
Instead:
data* p = (data*)lpParam;
p->a = ...;
p->b = ...;
p->c = ...;
The basic point here is that the thread function takes a void* argument, so you lose the type information. The first thing you want to do with it when your thread starts running is restore that type information so the compiler can check what you're doing is safe and sensible.
Your pointer arithmetic is off.
c is at offset 8 in the struct.
However:
*((char*)lpParam + 2) = "Es la una";
You cast lpParam to a char*. Char's have a size of 1 byte (on Windows at least.) You add two to the pointer, so you are writing to offset 2 bytes in the struct.
Your other pointer arithmetic happens to work since you cast lpParam to a float*, meaning (float*)lpParam + 1 writes to offset 4 in the struct.
As Omnifarius suggested, just cast lpParam to a pointer to the thread data structure and access the members through that.

Can I set a data breakpoint in runtime in System C (or in Plain Vanilla C++)?

I have a class in system-C with some data members as such:
long double x[8];
I'm initializing it in the construction like this:
for (i = 0; i < 8; ++i) {
x[i] = 0;
}
But the first time I use it in my code I have garbage there.
Because of the way the system is built I can't connect a debugger easily. Are there any methods to set a data breakpoint in the code so that it tells me where in the code the variables were actually changed, but without hooking up a debugger?
Edit:
#Prakash:
Actually, this is a typo in the question, but not in my code... Thanks!
You could try starting a second thread which spins, looking for changes in the variable:
#include <pthread.h>
void *ThreadProc(void *arg)
{
volatile long double *x = (volatile long double *)arg;
while(1)
{
for(int i = 0; i < 8; i++)
{
if(x[i] != 0)
{
__asm__ __volatile__ ("int 3"); // breakpoint (x86)
}
}
return 0; // Never reached, but placate the compiler
}
...
pthread_t threadID;
pthread_create(&threadID, NULL, ThreadProc, &x[0]);
This will raise a SIGTRAP signal to your application whenever any of the x values is not zero.
Just use printk/syslog.
It's old-fashioned, but super duper easy.
Sure, it will be garbage!
The code should have been as
for (i = 0; i < 8; ++i) {
x[i] = 0;
}
EDIT: Oops, Sorry for underestimating ;)
#Frank
Actually, that lets me log debug prints to a file. What I'm looking for is something that will let me print something whenever a variable changes, without me explicitly looking for the variable.
How about Conditional breakpoints? You could try for various conditions like first element value is zero or non zero, etc??
That's assuming I can easily connect a debugger. The whole point is that I only have a library, but the executable that linked it in isn't readily available.