跳转至

一个线程能访问另一个线程的栈吗

这是面试时遇到一个很有意思的问题。背过八股的同学都知道,一个进程里的线程共享代码段、全局数据段、BSS段、堆,只有栈是私有的,那么一个线程可以访问到另一个线程的栈吗?

一开始我以为线程栈既然是私有的,就可能有一些保护措施来避免被别的线程访问,但是面试官似乎对我这个回答并不满意。于是这里用实验探究一下,大体的思路就是使用一个指针执行一个线程里的局部变量,这个指针是一个全局变量,然后在另一个线程里通过这个指针去访问和修改局部变量。

#include <thread>
#include <cstdio>
#include <mutex>
#include <condition_variable>

std::condition_variable cv1, cv2;
std::mutex mtx1, mtx2;
bool cp1 = false, cp2 = false;

volatile int *ptr;  // 全局变量,fun1和fun2都可访问

void fun1() {
    volatile int localVal = 1234;
    ptr = &localVal;
    printf("fun1: %d\n", localVal);
    {
        std::unique_lock<std::mutex> lck1(mtx1);
        cp1 = true;
    }
    cv1.notify_one();  // 唤醒fun2

    std::unique_lock<std::mutex> lck2(mtx2);  // 等待fun2修改完成
    cv2.wait(lck2, [&]() { return cp2; });

    printf("fun1: %d\n", localVal);
}

void fun2() {
    std::unique_lock<std::mutex> lck1(mtx1); // 等待fun1取到地址
    cv1.wait(lck1, [&]() { return cp1; });
    printf("fun2: %d\n", *ptr);
    *ptr = 4321;
    printf("fun2: %d\n", *ptr);
    {
        std::unique_lock<std::mutex> lck2(mtx2);
        cp2 = true;
    }
    cv2.notify_one();  // 唤醒fun1
}

int main() {
    std::thread t1(fun1);
    std::thread t2(fun2);
    t1.join();
    t2.join();
}

结果

fun1: 1234
fun2: 1234
fun2: 4321
fun1: 4321

这里可以看出,其实一个线程可以访问整个进程空间的。