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打印会触发越界访问。 - 打印逻辑错误:最终测试打印时没有按线程下标取对应的数据元素,永远只打印数组第一个元素的内容。
- 缺少共享内存清理逻辑:运行一次后共享内存对象会留在系统中,重复运行可能出现异常。
代码修改说明
- 移除冗余的
shm_pointer_t结构体定义,直接把共享内存映射为shm_array_t类型 - 调整线程参数结构体,直接指向
shm_array_t类型的共享内存地址 - 调整
strncpy逻辑,复制后手动加终止符,同时扩大testc数组长度避免截断 - 修正打印逻辑,按索引取对应元素
- 程序退出前调用
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
相关产品推荐
相关产品推荐

