memcpy() 在多次迭代后创建分段错误
memcpy() creates segmentation fault after too many iterations
我正在尝试用 c 语言创建一个多线程库。这是 link to whole project(因为将代码粘贴到此处会导致文本过多)。
在文件 tests/MultithreadingTests.c
中,我正在测试 lib/systems/multithreading/src/ThreadPool.c
的功能。函数 add_work
将任何例程函数添加到利用 lib/sds/lists/src/Queue.c
和 lib/sds/lists/src/LinkedList.c
功能的工作队列中。在 MultithreadingTests.c
中,NUM_TESTS
定义了我添加到工作队列中的作业数,由 NUM_THREADS
执行
我遇到了一个奇怪的代码问题。如果 NUM_TESTS
任何数字小于 349,261
,代码工作得很好,但任何大于或等于 349,261
的数字都会导致分段错误。我试图检查分段错误发生的确切位置,发现它发生在 lib/sds/lists/src/Node.c
的第 29 行 memcpy(node->data, data, size);
错误的代码流是
tests/MultiThreadingTests.c
第 95 行 pool->add_work(pool, new_thread_job(routine, &arguments[i]));
lib/systems/multithreading/src/ThreadPool.c
第 150 行 thread_pool->work.push(&thread_pool->work, &job, sizeof(job));
lib/sds/lists/src/Queue.c
第 54 行 return q->list.insert(&q->list, q->list.length, data, size);
lib/sds/lists/src/LinkedLists.c
第 107 行 Node *node_to_insert = new_node(data, size);
lib/sds/lists/src/Node.c
第 29 行 memcpy(node->data, data, size);
我不确定为什么只有当作业数大于或等于 349,261 时才会出现此问题,而当作业数小于或等于 349,261 时不会出现此问题。
在函数new_thread_pool()
中,你既不
- 在
thread_pool.pool = malloc(sizeof(pthread_t) * num_threads);
和 中测试分配失败
- 在
pthread_create(&thread_pool.pool[i], NULL, generic_thread_function, &thread_pool);
中测试线程创建失败
尝试在任何系统上创建 349261 个或更多线程看起来更像是压力测试,而不是现实生活中的目的。测试错误并以可用的方式报告错误。
new_node
也不检查分配失败。除非您为此检测您的代码,否则您应该在 malloc()
调用周围使用包装器来检测分配失败并使用错误消息中止程序。
您的代码中的问题出在函数 mt_test_add_work()
中:您定义了一个具有自动存储功能的参数数组:
Arguments arguments[NUM_TESTS];
此对象在堆栈上分配,使用 8382264 字节的堆栈space。这对您的系统来说太多了,并且会导致调用链下的未定义行为,进一步的堆栈使用实际上会导致分段错误:Stack Overflow.
的典型案例
你应该从堆中分配这个对象并在退出函数之前释放它:
Arguments *arguments = malloc(sizeof(*arguments) * NUM_TESTS);
我正在尝试用 c 语言创建一个多线程库。这是 link to whole project(因为将代码粘贴到此处会导致文本过多)。
在文件 tests/MultithreadingTests.c
中,我正在测试 lib/systems/multithreading/src/ThreadPool.c
的功能。函数 add_work
将任何例程函数添加到利用 lib/sds/lists/src/Queue.c
和 lib/sds/lists/src/LinkedList.c
功能的工作队列中。在 MultithreadingTests.c
中,NUM_TESTS
定义了我添加到工作队列中的作业数,由 NUM_THREADS
我遇到了一个奇怪的代码问题。如果 NUM_TESTS
任何数字小于 349,261
,代码工作得很好,但任何大于或等于 349,261
的数字都会导致分段错误。我试图检查分段错误发生的确切位置,发现它发生在 lib/sds/lists/src/Node.c
的第 29 行 memcpy(node->data, data, size);
错误的代码流是
tests/MultiThreadingTests.c
第 95 行pool->add_work(pool, new_thread_job(routine, &arguments[i]));
lib/systems/multithreading/src/ThreadPool.c
第 150 行thread_pool->work.push(&thread_pool->work, &job, sizeof(job));
lib/sds/lists/src/Queue.c
第 54 行return q->list.insert(&q->list, q->list.length, data, size);
lib/sds/lists/src/LinkedLists.c
第 107 行Node *node_to_insert = new_node(data, size);
lib/sds/lists/src/Node.c
第 29 行memcpy(node->data, data, size);
我不确定为什么只有当作业数大于或等于 349,261 时才会出现此问题,而当作业数小于或等于 349,261 时不会出现此问题。
在函数new_thread_pool()
中,你既不
- 在
thread_pool.pool = malloc(sizeof(pthread_t) * num_threads);
和 中测试分配失败
- 在
pthread_create(&thread_pool.pool[i], NULL, generic_thread_function, &thread_pool);
中测试线程创建失败
尝试在任何系统上创建 349261 个或更多线程看起来更像是压力测试,而不是现实生活中的目的。测试错误并以可用的方式报告错误。
new_node
也不检查分配失败。除非您为此检测您的代码,否则您应该在 malloc()
调用周围使用包装器来检测分配失败并使用错误消息中止程序。
您的代码中的问题出在函数 mt_test_add_work()
中:您定义了一个具有自动存储功能的参数数组:
Arguments arguments[NUM_TESTS];
此对象在堆栈上分配,使用 8382264 字节的堆栈space。这对您的系统来说太多了,并且会导致调用链下的未定义行为,进一步的堆栈使用实际上会导致分段错误:Stack Overflow.
的典型案例你应该从堆中分配这个对象并在退出函数之前释放它:
Arguments *arguments = malloc(sizeof(*arguments) * NUM_TESTS);