在循环中创建和加入 pthread
Creating and joining pthreads in a loop
我在通过循环创建线程时遇到了一个奇怪的问题。我有一个线程数组,用户可以指定从 1 到 25 的线程数。我 运行 遇到的一个特定问题是在循环遍历并加入线程数组中的单独线程时出现段错误。我调试了它,发现数组中的线程值是零散分布的。例如,如果用户指定了 9 个线程,而数组总共包含 25 个可能的线程,那么数组将如下所示:
{0, 0, 12332342, 0, 0, 123212313, ...}
基本上,填充的索引不是预期的从索引 0 到 9,而是分布在整个数组中。
我的代码有点乱,所以我只包含了相关部分,如果需要更多上下文,请告诉我:
int max_chld_threads = p_args->num_threads - 1;
int chld_threads_delay = p_args->cons_chld_delay;
pthread_t chld_threads[25];
consargs chld_c_args[25];
char chld_name[2] = {'B', 0};
int thd_cnt = 0;
size_t max_char = MAX_CHAR_PER_LINE - 1;
char term_sentinel[] = "@$%#";
int i;
char *cur_file;
char *line;
void *retval;
if ((line = (char *) malloc(max_char * sizeof(char))) == NULL) {
perror("Malloc failed");
exit(1);
}
//Opening files in file array
for (i = 0; i < num_files; i++) {
cur_file = *(file_path_lst + i);
if ((fp = fopen(cur_file, "r")) == NULL) {
perror("Cannot open");
continue;
}
while (getline(&line, &max_char, fp) != -1) {
put (&buffer, line);
//Creates new child thread if buffer is full
if (thd_cnt < max_chld_threads && buffer.full == 1) {
//Copies the argument which contains a thread's name
strncpy(chld_c_args[thd_cnt].name, chld_name, sizeof(chld_c_args));
chld_c_args[thd_cnt].delay = chld_threads_delay;
if (pthread_create (&chld_threads[thd_cnt], NULL, consumer,
(void *) &chld_c_args[thd_cnt]) != 0) {
perror("Child consumer thread creation failed");
continue;
}
//Increment the letter for next child thread
chld_name[0]++;
thd_cnt++;
}
}
fclose(fp);
}
put (&buffer, term_sentinel);
/* Join here */
for (i = 0; i < thd_cnt; i++) { //SEGFAULTS here
pthread_join (chld_threads[i], &retval);
}
参数:
struct consargs
{
int delay;
char name[2];
};
不确定这是否会导致您的特定问题,但您可能在这一行中遇到了缓冲区溢出:
strncpy(chld_c_args[thd_cnt].name, chld_name, sizeof(chld_c_args));
应该是:
strncpy(chld_c_args[thd_cnt].name, chld_name,
sizeof(chld_c_args[thd_cnt].name));
strncpy 将用零填充目标。所以你可能会覆盖 thd_cnt (以及其他变量)。
我在通过循环创建线程时遇到了一个奇怪的问题。我有一个线程数组,用户可以指定从 1 到 25 的线程数。我 运行 遇到的一个特定问题是在循环遍历并加入线程数组中的单独线程时出现段错误。我调试了它,发现数组中的线程值是零散分布的。例如,如果用户指定了 9 个线程,而数组总共包含 25 个可能的线程,那么数组将如下所示:
{0, 0, 12332342, 0, 0, 123212313, ...}
基本上,填充的索引不是预期的从索引 0 到 9,而是分布在整个数组中。
我的代码有点乱,所以我只包含了相关部分,如果需要更多上下文,请告诉我:
int max_chld_threads = p_args->num_threads - 1;
int chld_threads_delay = p_args->cons_chld_delay;
pthread_t chld_threads[25];
consargs chld_c_args[25];
char chld_name[2] = {'B', 0};
int thd_cnt = 0;
size_t max_char = MAX_CHAR_PER_LINE - 1;
char term_sentinel[] = "@$%#";
int i;
char *cur_file;
char *line;
void *retval;
if ((line = (char *) malloc(max_char * sizeof(char))) == NULL) {
perror("Malloc failed");
exit(1);
}
//Opening files in file array
for (i = 0; i < num_files; i++) {
cur_file = *(file_path_lst + i);
if ((fp = fopen(cur_file, "r")) == NULL) {
perror("Cannot open");
continue;
}
while (getline(&line, &max_char, fp) != -1) {
put (&buffer, line);
//Creates new child thread if buffer is full
if (thd_cnt < max_chld_threads && buffer.full == 1) {
//Copies the argument which contains a thread's name
strncpy(chld_c_args[thd_cnt].name, chld_name, sizeof(chld_c_args));
chld_c_args[thd_cnt].delay = chld_threads_delay;
if (pthread_create (&chld_threads[thd_cnt], NULL, consumer,
(void *) &chld_c_args[thd_cnt]) != 0) {
perror("Child consumer thread creation failed");
continue;
}
//Increment the letter for next child thread
chld_name[0]++;
thd_cnt++;
}
}
fclose(fp);
}
put (&buffer, term_sentinel);
/* Join here */
for (i = 0; i < thd_cnt; i++) { //SEGFAULTS here
pthread_join (chld_threads[i], &retval);
}
参数:
struct consargs
{
int delay;
char name[2];
};
不确定这是否会导致您的特定问题,但您可能在这一行中遇到了缓冲区溢出:
strncpy(chld_c_args[thd_cnt].name, chld_name, sizeof(chld_c_args));
应该是:
strncpy(chld_c_args[thd_cnt].name, chld_name,
sizeof(chld_c_args[thd_cnt].name));
strncpy 将用零填充目标。所以你可能会覆盖 thd_cnt (以及其他变量)。