You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言多线程场景下对semaphore信号量做递减操作时哪里出错了?

信号量使用错误排查与修复

现有代码的核心问题

  • 信号量发布时机错误:当前thread_A先执行sem_post(&sem)再执行malloc分配数组,会导致function_B拿到信号量时array还未完成初始化,直接访问触发野指针崩溃。
  • 信号量计数逻辑错误:信号量初始值为0,thread_A每次循环都执行一次post,如果function_B没有及时消费信号量,信号量计数会累计到大于1,下次循环还未执行malloc时function_B就能成功获取信号量,同样会访问非法内存。
  • 数组释放前无同步逻辑:thread_A休眠2秒后直接执行free(array),没有判断当前是否有线程正在写入数组,会触发释放后使用(UAF)的内存错误。
  • 共享变量无并发保护:array、position都是多线程共享的全局变量,没有加锁保护的情况下并发访问会出现竞争条件,比如position计数异常、array指针读取到半初始化的值。
  • sem_trywait返回值判断逻辑倒置:sem_trywait成功获取信号量时返回值为0,失败返回非0,当前代码if(sem_trywait(&sem))的判断逻辑会导致获取信号量成功时不执行写入,获取失败反而进入写入分支,完全不符合预期。

修复示例代码

全局变量与初始化

#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

int *array = NULL;
int position = 0;
sem_t sem;
// 新增互斥锁保护array、position等共享变量
pthread_mutex_t array_mutex = PTHREAD_MUTEX_INITIALIZER;

// 主函数初始化逻辑
int main() {
    // 信号量初始值仍为0
    sem_init(&sem, 0, 0);
    // 后续线程创建逻辑省略
    return 0;
}

thread_A 实现修复

static void *thread_A(void *p_vp_arg)
{
    while (1)
    {
        pthread_mutex_lock(&array_mutex);
        array = malloc(1024 * sizeof(int));
        position = 0; // 每次分配新数组后重置写入位置
        pthread_mutex_unlock(&array_mutex);
        
        sem_post(&sem); // 数组分配完成后再发布信号量,通知可写入
        
        /* 原有业务逻辑 */
        sleep(2);
        
        // 释放前清空未消费的信号量,避免下次循环前被错误获取
        sem_trywait(&sem);
        
        pthread_mutex_lock(&array_mutex);
        free(array);
        array = NULL; // 释放后置空,避免野指针访问
        pthread_mutex_unlock(&array_mutex);
    }
}

function_B 实现修复

static void function_B(int variable){
    // 正确判断信号量获取成功的返回值
    if(sem_trywait(&sem) == 0){
        pthread_mutex_lock(&array_mutex);
        // 双重校验避免极端情况下数组已被释放、写入越界
        if(array != NULL && position < 1024){
            printf("I can write into the array\n");
            array[position] = variable;
            position += 1;
        }
        pthread_mutex_unlock(&array_mutex);
        // 如果需要支持数组有效期内多次写入,此处新增 sem_post(&sem) 归还信号量即可
    }
}

可选优化方案

如果业务需要在数组的2秒有效期内支持任意次数的写入,可以将信号量替换为读写锁:数组分配完成后加读锁,释放数组前解读锁,写入操作尝试加读锁,成功即可执行写入,逻辑会更简洁清晰。

内容的提问来源于stack exchange,提问作者Report Feedback

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 22:15:00