- 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/
我目前正在尝试基于哈希表构建字典。逻辑是:有一个名为 HashTable 的结构,其中包含以下内容: HashFunc HashFunc; PrintFunc PrintEntry; CompareF
如果我有一个指向结构/对象的指针,并且该结构/对象包含另外两个指向其他对象的指针,并且我想删除“包含这两个指针的对象而不破坏它所持有的指针”——我该怎么做这样做吗? 指向对象 A 的指针(包含指向对象
像这样的代码 package main import "fmt" type Hello struct { ID int Raw string } type World []*Hell
我有一个采用以下格式的 CSV: Module, Topic, Sub-topic 它需要能够导入到具有以下格式的 MySQL 数据库中: CREATE TABLE `modules` ( `id
通常我使用类似的东西 copy((uint8_t*)&POD, (uint8_t*)(&POD + 1 ), back_inserter(rawData)); copy((uint8_t*)&PODV
错误 : 联合只能在具有兼容列类型的表上执行。 结构(层:字符串,skyward_number:字符串,skyward_points:字符串)<> 结构(skyward_number:字符串,层:字符
我有一个指向结构的指针数组,我正在尝试使用它们进行 while 循环。我对如何准确初始化它并不完全有信心,但我一直这样做: Entry *newEntry = malloc(sizeof(Entry)
我正在学习 C,我的问题可能很愚蠢,但我很困惑。在这样的函数中: int afunction(somevariables) { if (someconditions)
我现在正在做一项编程作业,我并没有真正完全掌握链接,因为我们还没有涉及它。但是我觉得我需要它来做我想做的事情,因为数组还不够 我创建了一个结构,如下 struct node { float coef;
给定以下代码片段: #include #include #define MAX_SIZE 15 typedef struct{ int touchdowns; int intercepti
struct contact list[3]; int checknullarray() { for(int x=0;x<10;x++) { if(strlen(con
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: Empty “for” loop in Facebook ajax what does AJAX call
我刚刚在反射器中浏览了一个文件,并在结构构造函数中看到了这个: this = new Binder.SyntaxNodeOrToken(); 我以前从未见过该术语。有人能解释一下这个赋值在 C# 中的
我经常使用字符串常量,例如: DICT_KEY1 = 'DICT_KEY1' DICT_KEY2 = 'DICT_KEY2' ... 很多时候我不介意实际的文字是什么,只要它们是独一无二的并且对人类读
我是 C 的新手,我不明白为什么下面的代码不起作用: typedef struct{ uint8_t a; uint8_t* b; } test_struct; test_struct
您能否制作一个行为类似于内置类之一的结构,您可以在其中直接分配值而无需调用属性? 前任: RoundedDouble count; count = 5; 而不是使用 RoundedDouble cou
这是我的代码: #include typedef struct { const char *description; float value; int age; } swag
在创建嵌套列表时,我认为 R 具有对列表元素有用的命名结构。我有一个列表列表,并希望应用包含在任何列表中的每个向量的函数。 lapply这样做但随后剥离了列表的命名结构。我该怎么办 lapply嵌套列
我正在做一个用于学习目的的个人组织者,我从来没有使用过 XML,所以我不确定我的解决方案是否是最好的。这是我附带的 XML 文件的基本结构:
我是新来的 nosql概念,所以当我开始学习时 PouchDB ,我找到了这个转换表。我的困惑是,如何PouchDB如果可以说我有多个表,是否意味着我需要创建多个数据库?因为根据我在 pouchdb
我是一名优秀的程序员,十分优秀!