- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我被困在这个问题上,似乎无法弄清楚发生了什么。对于背景,我试图将一个结构传递给 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/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!