C语言将argv参数作为线程数使用触发浮点异常如何解决?
问题解答
核心错误说明
你不需要通过指针实现相关逻辑,浮点异常的触发原因是变量作用域错误导致的除零操作:
你在全局作用域定义了THREAD_COUNT变量,默认初始值为0,又在main函数中重新定义了同名的局部变量int THREAD_COUNT = atoi(argv[1]);,局部变量仅在main函数范围内生效,全局THREAD_COUNT从未被赋值,process函数执行100000000/THREAD_COUNT时就会触发除零的浮点异常。只需要去掉main函数里THREAD_COUNT、FUNCTION前的int声明,直接给全局变量赋值即可解决该问题。
其余需要修复的代码问题
- 4线程创建逻辑错误:连续两次调用
pthread_create创建thread3,未初始化thread4,后续pthread_join等待未初始化变量会触发未定义行为 - 全局变量
balance多线程并发读写未加锁,存在竞态条件,最终输出结果会和预期不符 - 头文件包含格式错误:
#include <"transact.h">应改为#include "transact.h",自定义头文件不需要用尖括号包裹 - 缺少命令行参数校验:用户未传够参数时直接访问
argv[1]、argv[2]会触发段错误,需要先判断argc >=3再读取参数 - 缺少输入合法性校验:如果用户输入的第一个参数是非数字、0或负数,会导致
THREAD_COUNT异常,触发除零或逻辑错误 process函数缺少返回值:void *类型的函数必须返回指针,可补充return NULL;
修复后参考代码
#include "transact.h" #include <pthread.h> #include <stdio.h> #include <stdlib.h> int balance = 100000000; int THREAD_COUNT; int FUNCTION; // 互斥锁保护balance并发读写 pthread_mutex_t balance_lock = PTHREAD_MUTEX_INITIALIZER; void * process(void * arg) { for(int i = 0; i < 100000000/THREAD_COUNT; i++) { int transaction = getTransaction(i); pthread_mutex_lock(&balance_lock); balance = balance - 1; pthread_mutex_unlock(&balance_lock); printf("%d : %d\n", i, transaction); } return NULL; } int main(int argc, char * argv[]) { // 校验参数数量 if (argc < 3) { printf("参数不足,使用方式:./程序名 线程数 功能编号\n"); return 1; } // 直接给全局变量赋值,不要重复定义 THREAD_COUNT = atoi(argv[1]); FUNCTION = atoi(argv[2]); // 校验线程数合法性 if (THREAD_COUNT <=0 || (THREAD_COUNT != 2 && THREAD_COUNT !=4 && THREAD_COUNT !=8)) { printf("线程数仅支持输入2、4、8\n"); return 1; } if (FUNCTION == 0) { // 动态创建线程,无需写死多分支逻辑 pthread_t threads[THREAD_COUNT]; for (int i = 0; i < THREAD_COUNT; i++) { pthread_create(&threads[i], NULL, process, NULL); } for (int i = 0; i < THREAD_COUNT; i++) { pthread_join(threads[i], NULL); } printf("Balance is: %d \n", balance); } else { printf("功能编号不合法\n"); } return 0; }
内容的提问来源于stack exchange,提问作者AMCode96
相关产品推荐
相关产品推荐

