读变量搞砸了吗?

时间:2010-05-21 12:16:39

标签: linux multithreading printf

我们有以下代码行:

printf("%d\n", toc->runlist.next);
printf("%d\n", toc->runlist.next);

这些是定义:

typedef struct thread_overview_control{
    int id[NR_UTHREADS];
    list_t runlist;
    int active_counter;
    int main_thread;
    int need_resched;
} thread_overview_control;

thread_overview_control* toc;

我要做的是实现用户线程。出于某种原因,上面代码在我们的测试运行压缩点的输出是:

12345678  //some address
0         //NOW IT'S NULL?!?!?!

怎么会发生这种情况?我们所做的只是读取一个变量。 奇怪的是,没有printf就没有崩溃。发生了什么事?

5 个答案:

答案 0 :(得分:3)

很可能另一个线程正在访问(和更改)两次调用printf()之间的变量。如果删除printf语句,时间会发生变化,行为也会不同。

如果多个线程确实正在访问数据,则需要使用互斥锁保护它。

答案 1 :(得分:1)

printf()不会修改其可变参数。但是,printf()是一个成本足以暴露线程之间没有(或不正确)锁定引起的竞争的操作。

您要使用的是互斥锁:

pthread_mutex_t thread_lock = PTHREAD_MUTEX_INITIALIZER;

void *thread_func(void *threadarg)
{
    thread_overview_control *toc = (thread_overview_control *)threadarg;

    pthread_mutex_lock(&thread_lock);
    printf("%d\n", toc->runlist.next);
    printf("%d\n", toc->runlist.next);
    pthread_mutex_unlock(&thread_lock);

    ....

在该示例中,pthread_mutex_lock()将阻止另一个线程是否具有锁定。如果您的函数在等待锁定可用时可以执行其他有用的工作,请尝试pthread_mutex_trylock(),也许在while()循环中。

确保每个线程都可以通过使其成为全局(或将其置于每个可以访问的结构中)来访问互斥锁。使用PTHREAD_MUTEX_INITIALIZER初始化互斥锁同样重要,否则您将面临锁定的风险,而没有任何线程实际持有它。

每当您阅读或写信*toc时,您都需要获得锁定。

答案 2 :(得分:1)

尝试在valgrind下运行您的程序。它会指出您可能遇到的任何与内存相关的错误。

答案 3 :(得分:1)

虽然竞争条件是一个可能的原因,但听起来你的问题比我希望看到的解释更加一致。

另一种可能性是一个普通的旧野指针。你是如何初始化toc的?如果它最终指向已释放的堆栈内存,则第一个printf()调用很容易踩到它。

答案 4 :(得分:0)

什么是list_t?这是普通的C吗?请注意,在C ++中可以simulate a "property"(有点),因此调用runlist.next实际上会调用某个方法,它可能是伪装的迭代器。

但是,Vicky的答案对我来说似乎更有可能。