-2

Can you help me understand why this code is giving me a segfault as below? Could there be a problem in the way I create threads? I'm having difficulty understanding the issue. Please note that I have simplified the question as much as possible - I am compiling the code with -O3 and getting a zero page error, but the code is valid.

#include <fstream>
#include <sstream>
#include <thread>
#include <iostream>
#include <algorithm>
#include <new>
#include <thread>
#include <string>

class temp {
private:
    std::thread m_thread;
    std::vector<std::string> m_tokens;

public:
    temp()
    {
        m_thread = std::thread(&temp::run, this);
    }

    void run()
    {
        while (1) {
            std::string token;
            std::cin >> token;

            if (std::ranges::find(m_tokens, token) != m_tokens.end()) {
                std::cout << "duplicate token" << token << "\n";
                continue;
            }

            m_tokens.push_back(token);

            std::cout << token << " added\n";
        }
    }
};

int main(int argc, char **argv)
{
    temp t;
    
    while (1)
        ;
    
    return EXIT_SUCCESS;
}

ThreadSanitizer:DEADLYSIGNAL
==19246==ERROR: ThreadSanitizer: SEGV on unknown address 0x000000000000 (pc 0x7f81d5f98880 bp 0x7b0800000020 sp 0x7f81d30bf298 T19247)
==19246==The signal is caused by a WRITE memory access.
==19246==Hint: address points to the zero page.
    #0 __tsan_func_entry <null> (libtsan.so.0+0x9e880)
    #1 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (temp::*)(), temp*> > >::_M_run() /opt/rh/devtoolset-11/root/usr/include/c++/11/bits/std_thread.h:211 (trading+0x41e3a3)
    #2 execute_native_thread_routine <null> (trading+0x437ab3)
    #3 start_thread <null> (libpthread.so.0+0x7ea4)
    #4 clone <null> (libc.so.6+0xfeb0c)

ThreadSanitizer can not provide additional info.
SUMMARY: ThreadSanitizer: SEGV (/lib64/libtsan.so.0+0x9e880) in __tsan_func_entry
==19246==ABORTING

How is it possible that the code runs without any issues when I run it directly, but gives a segfault error when run as a thread?

273K
  • 29,503
  • 10
  • 41
  • 64
avatli
  • 610
  • 6
  • 16
  • 5
    `while (1) ;` is undefined behaviour - check this has not been removed by the compiler. – Richard Critten Mar 05 '23 at 19:02
  • 1
    Doing input in a new thread is not really a good idea. And this whole program, as it is shown to us, is not a good candidate for using threads. – Some programmer dude Mar 05 '23 at 19:05
  • 1
    _"but the code is valid"_ This code has guaranteed Undefined Behavior, which you should not consider "valid" if you have expectations regarding this program's behavior. – Drew Dormann Mar 05 '23 at 19:17
  • changed the code, now it joins but still the same error is here – avatli Mar 05 '23 at 19:19
  • 1
    After getting valid answer(s), it is not considered good form to change your question to make existing answers incorrect. – Drew Dormann Mar 05 '23 at 19:21
  • @DrewDormann None of the answers were valid as they did not focus on the question itself – avatli Mar 05 '23 at 19:23
  • What OS, compiler, standard library, etc. are you testing this with? What is the input you are using? – user17732522 Mar 05 '23 at 19:24
  • 1
    Is this the Real Code that is producing this segfault? I'm [having great difficulty](https://godbolt.org/z/vYcbcvnqn) finding any compiler that can compile this exact code. – Drew Dormann Mar 05 '23 at 19:24
  • 1
    You are missing `-pthread` in the compiler invocation. [...] Nevermind, that's not the linking step. Do you use `-pthread` in the linking step? – user17732522 Mar 05 '23 at 19:35
  • 1
    Don't edit the code and change the question after you have got an answer to your original question. You can delete the wrong question and try to ask again. – 273K Mar 05 '23 at 19:47
  • Given the two edits of the question, and the concern of the cout etc in the thread, what happens when you remove the IO from the thread (replace with some fixed token value)? Does it give the same error? – Niall Mar 05 '23 at 20:20

1 Answers1

3

You must call .join() on the std::thread object in the main thread (e.g. in temp's destructor) in order to have the main thread wait until the thread managed by the std::thread exits.

Infinite loops are no replacement for that and infinite loops without observable side effect have undefined behavior in C++. Compilers do optimize under the assumption that they can never be executed, sometimes going as far as compiling complete nonsense for functions containing them (e.g. Clang) or simply removing them.

user17732522
  • 53,019
  • 2
  • 56
  • 105