gpt4 book ai didi

c++ - 无法访问传递给 pthread 的结构中的结构元素

转载 作者:行者123 更新时间:2023-11-30 05:19:48 25 4
gpt4 key购买 nike

我被困在这个问题上,似乎无法弄清楚发生了什么。对于背景,我试图将一个结构传递给 3 个 pthreads,然后在线程中修改该结构,然后将每个结构存储回主线程,并将每个结构获得的部分结果相加以加快这部分我的代码似乎是性能的主要瓶颈。我在另一个用 C 编写的项目中使用了与此非常相似的代码,但是当我将它复制到这个 C++ 程序中并修改它以适应这个问题时,我遇到了一些奇怪的错误。

首先,我必须进行一些我不必在 C 中进行的转换才能使其编译。由于我将 thread_work 函数作为方法包含在类中,它看到的类型为 (void * (AIShell::*)(void *),因此我需要将其转换为 (void * (*)(void *),这允许它编译和运行,但它给了我一个编译器警告。我将它作为一个方法而不是一个函数包含在内的原因是我可以从这个方法中调用另一个类方法,所以它是必需的。有吗我应该以任何方式修改我的代码以消除这种情况,还是这只是在类中使用我的线程函数的不幸副作用?

AIShell.cpp: In member function ‘double AIShell::heuristic(int**)’:
AIShell.cpp:173:78: warning: converting from ‘void* (AIShell::*)(void*)’ to ‘void* (*)(void*)’ [-Wpmf-conversions]
th = pthread_create(&new_threads[i], &attr, (void * (*)(void *)) &AIShell::thread_work, (void *) (se+i));

其次,也是最重要的一点,我在运行代码时遇到了段错误。我已经缩小了问题发生的范围,每当我尝试访问我传递给线程的结构成员(即执行 se->start_count)时,它就会在我的 thread_work 函数中发生:

125 struct start_end
126 {
127 int ** board;
128 int start_col;
129 int end_col;
130 int start_row;
131 int end_row;
132 double total;
133 };
134
135 void * AIShell::thread_work(void * arg)
136 {
137 struct start_end * se = (struct start_end *) malloc(sizeof(struct start_end));
138 se = (struct start_end *) arg;
139 printf("\nse->total = %lg; se->start_row = %d; se->start_col = %d\n\n", se->total, se->start_row, se->start_c ol);
140 fflush(stdout);
141 for (int row = se->start_row; row != se->end_row; row++)
142 {
143 for (int col = se->start_col; col != se->end_col; col++)
144 {
145 se->total += check8(se->board, col, row);
146 }
147 }
148 printf("asdfasdfasfdasdfasdfasdfasdfasdfasdfasdf\n");
149 fflush(stdout);
150 pthread_exit((void *)se);
151 }

当它到达这部分代码时,也就是每个线程运行的部分,它最初在 for 循环开始的第 141 行失败,但是在第 139 行添加打印语句后,它在那里失败,这证实了问题在于引用结构成员。

但是,如果我在第 138 行的“arg”之前添加一个“&”,那么它看起来像这样:

138     se = (struct start_end *) &arg;

它不再出现段错误,但它会获取垃圾值,这会在以后破坏我的一些代码。据我所知,在将结构传递给线程之前,我已经正确地为结构分配了值,所以我不太确定这里发生了什么。

这段代码是充当“主线程”的方法,它初始化结构,产生其他线程,并应该从每个线程中取回结果并将它们相加以获得最终结果。它本身也充当一个线程,所以我在这里使用了一个与上面函数类似的代码段,这样我就可以使用我所有的资源;)

153 double AIShell::heuristic(int ** board)
154 {
155 pthread_t new_threads[3] = {0};
156 pthread_attr_t attr;
157 int th;
158 long t;
159 struct start_end * se;
160 se = (struct start_end *) malloc(3*sizeof(struct start_end));
161
162 pthread_attr_init(&attr);
163 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
164
165 for (int i = 0; i <3; i ++)
166 {
167 (se+i)->board = copy(board);
168 (se+i)->start_row = numRows/4*i;
169 (se+i)->end_row = numRows/4*(i+1);
170 (se+i)->start_col = numCols/4*i;
171 (se+i)->end_col = numCols/4*(i+1);
172 (se+i)->total = 0;
173 th = pthread_create(&new_threads[i], &attr, (void * (*)(void *)) &AIShell::thread_work, (void *) (se+i));
174 if (th)
175 {
176 perror("pthread_create");
177 exit(1);
178 }
179 }
180
181
182 int start_row = numRows/4*3;
183 int end_row = numRows;
184 int start_col = numCols/4*3;
185 int end_col = numCols;
186 int total = 0;
187
188 for (int row = start_row; row != end_row; row++)
189 {
190 for (int col = start_col; col != end_col; col++)
191 {
192 total += check8(board, col, row);
193 }
194 }
195
196 for (int i = 0; i != 3; i++)
197 {
198 th = pthread_join(new_threads[i], (void **) (se+i));
199 if (th)
200 {
201 perror("pthread_join");
202 exit(1);
203 }
204 }
205
206 for (int i = 0; i != 3; i++)
207 {
208 total += (se+i)->total;
209 free((se+i));
210 }
211
212 pthread_attr_destroy(&attr);
213
214 free(se);
215
216 return total;
217 }

我意识到这样做对我来说是非常“C”的,我可以用“new”或其他什么来做,但正如我所说,我改编了“C”项目中的代码以用于这个“C++"项目,并希望以这种方式进行,而不必重写所有内容。我也不肯定我为此正确地“释放”了,但它甚至还没有出现在我的代码中,所以这更像是一个次要问题。因此,尽管如此,有没有人看到我在这里做错了什么?我已经尝试了很多东西,但似乎无法让它工作:/

最佳答案

一方面,你在那里泄漏了内存。您 malloc 内存并在线程函数中将指针分配给 se,然后将 arg 的值分配给同一指针。由第一行 thread_work 分配的内存将丢失。

其次,为什么要这样转换 (void * (*)(void *)) &AIShell::thread_work

函数声明为

void * AIShell::thread_work(void * arg)

不需要这样的转换,除非..它是类的方法并且 AIShell 是类,而不是命名空间。那么 AIShell 是一个类吗?在那种情况下,您要么需要一个静态函数,要么使用 std::bind 为其生成一个包装器,非静态方法实际上隐藏了“this”参数。

线

se = (struct start_end *) &arg;

是错误的,因为您获取了参数 arg 的地址(应该在堆栈中?)并将其转换为指向结构的指针,而实际上该内存包含指针。它不会产生段错误,因为您很可能似乎访问了堆栈或数据段,那里没有违规。调试程序并检查 worker 中 arg 的值,并将其与提供给 pthread_create 的 se+i 值进行比较。首先是指针的值。

关于c++ - 无法访问传递给 pthread 的结构中的结构元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40965911/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com