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

C语言用pthreads更新共享内存时调用strncpy出现段错误求助

问题原因与修复方案

核心错误点

  • 共享内存结构设计错误:你将共享内存映射为shm_pointer_t类型,该结构体仅包含一个shm_array_t*指针,你没有对这个指针做初始化,它是指向非法地址的野指针,线程中访问thread_array->shared_ptr->array_ptr时自然触发段错误。完全不需要单独定义指针结构体,直接把共享内存映射为存储实际数据的shm_array_t类型即可。
  • 字符串未加终止符:"TESTING"共7个字符(含末尾隐含的\0),你用strncpy复制6个字符到长度为6的testc数组中,数组没有空间存储终止符,后续用%s打印会触发越界访问。
  • 打印逻辑错误:最终测试打印时没有按线程下标取对应的数据元素,永远只打印数组第一个元素的内容。
  • 缺少共享内存清理逻辑:运行一次后共享内存对象会留在系统中,重复运行可能出现异常。

代码修改说明

  1. 移除冗余的shm_pointer_t结构体定义,直接把共享内存映射为shm_array_t类型
  2. 调整线程参数结构体,直接指向shm_array_t类型的共享内存地址
  3. 调整strncpy逻辑,复制后手动加终止符,同时扩大testc数组长度避免截断
  4. 修正打印逻辑,按索引取对应元素
  5. 程序退出前调用shm_unlink清理共享内存对象

修正后可运行代码

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

#define THREADCOUNT 3
#define ARRAYCOUNT 3
// 直接按实际数据大小计算共享内存长度,避免手动算错
#define SHM_SIZE sizeof(shm_array_t)
#define KEY_NAME "test"

const int threadNumArray[3] = {0, 1, 2};

/* 数据结构体 */
typedef struct struct_test
{
    int testi;     /* 4字节 */
    float testf;   /* 4字节 */
    char testc[7]; /* 改大1字节存终止符 */
} test_t;

/* 数据数组结构体 */
typedef struct shared_array_test
{
    test_t test_array[ARRAYCOUNT];
} shm_array_t;

/* 线程结构体:包含数据数组指针和线程编号 */
typedef struct thread_array_test
{
    int threadNum;
    shm_array_t *shared_ptr;
} thread_array_t;

void *test_process(void *arg)
{
    thread_array_t *thread_array = (thread_array_t *)arg;
    test_t *test_data = &thread_array->shared_ptr->test_array[thread_array->threadNum];
    char *testing = "TESTING";
    strncpy(test_data->testc, testing, sizeof(test_data->testc)-1);
    test_data->testc[sizeof(test_data->testc)-1] = '\0'; // 手动加终止符保证字符串合法
    test_data->testf = 10.2 + thread_array->threadNum; // 加下标区分不同线程的数据
    test_data->testi = 2 + thread_array->threadNum;
    return NULL;
}

int main()
{
    /* 先清理可能残留的共享内存,避免重复运行报错 */
    shm_unlink(KEY_NAME);
    /* 创建共享内存段 */
    int shm_test;
    shm_array_t *shared_test;
    if ((shm_test = shm_open(KEY_NAME, O_CREAT | O_RDWR, 0666)) < 0)
    {
        perror("shm_open");
        return -1;
    }
    ftruncate(shm_test, SHM_SIZE);
    if ((shared_test = mmap(0, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_test, 0)) == MAP_FAILED)
    {
        perror("mmap");
        return -1;
    }
    close(shm_test); // 映射完成后可以关闭文件描述符

    /* 为每个线程创建结构体 */
    thread_array_t thread_array[THREADCOUNT];
    for (int i = 0; i < THREADCOUNT; i++)
    {
        thread_array[i].shared_ptr = shared_test;
        thread_array[i].threadNum = threadNumArray[i];
    }

    /* 启动线程 */
    pthread_t threads[THREADCOUNT];
    for (int i = 0; i < THREADCOUNT; i++)
    {
        pthread_create(&threads[i], NULL, test_process, thread_array + i);
    }
    /* 等待线程结束 */
    for (int i = 0; i < THREADCOUNT; i++)
    {
        pthread_join(threads[i], NULL);
    }
    /* 测试:打印所有线程的数据 */
    for (int i = 0; i < THREADCOUNT; i++)
    {
        printf("线程%d测试:字符串=%s 浮点数=%.1f 整数=%d\n", 
               i, shared_test->test_array[i].testc,
               shared_test->test_array[i].testf,
               shared_test->test_array[i].testi);
    }
    /* 清理共享内存 */
    munmap(shared_test, SHM_SIZE);
    shm_unlink(KEY_NAME);
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 20:54:03