我在下面的代码中第8行遇到了分段错误。
typedef struct _my_struct {
int pArr[21];
int arr1[8191];
int arr2[8191];
int m;
int cLen;
int gArr[53];
int dArr[8191];
int data[4096];
int rArr[53];
int eArr[1024];
};
void *populate_data(void *arg) {
1 register int mask =1, iG;
2 struct _my_struct *var ;
3 var = arg; // arg is passed as initialized struct variable while creating thread
4 var->m = 13;
5 var->arr2[var->m] = 0;
6 for (iG = 0; iG < var->m; iG++) {
7 var->arr2[iG] = mask;
8 var->arr1[var->arr2[iG]] = iG;
9 if (var->pArr[iG] != 0) // pArr[]= 1011000000001
10 var->arr2[var->m] ^= mask;
11 mask <<= 1;
12 }
13 var->arr1[var->arr2[var->m]] = var->m;
14 mask >>= 1;
15 for (iG = var->m+ 1; iG < var->cLen; iG++) {
16 if (var->arr2[iG - 1] >= mask)
17 var->arr2[iG] = var->arr2[var->m] ^ ((var->arr2[iG- 1] ^ mask) << 1);
18 else
19 var->arr2[iG] = var->arr2[iG- 1] << 1;
20 var->arr1[var->arr2[iG]] = iG;
21 }
22 var->arr1[0] = -1;
}
这是线程函数:
void main() {
unsigned int tid;
struct _my_struct *instance = NULL;
instance = (struct _my_struct *)malloc(sizeof(_my_struct ));
start_thread(&tid , 119312, populate_data, instance );
}
int
start_thread(unsigned int *tid, int stack_size, void * (*my_function)(void *), void *arg)
{
pthread_t ptid = -1;
pthread_attr_t pattrib;
pthread_attr_init(&pattrib);
if(stack_size > 0)
{
pthread_attr_setstacksize(&pattrib, stack_size);
}
else
{
pthread_attr_destroy(&pattrib);
return -1;
}
pthread_create(&ptid, &pattrib, my_function, arg);
pthread_attr_destroy(&pattrib);
return 0;
}
一旦我通过gdb调试它,就会出现此错误,
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffdfec80700 (LWP 22985)]
0x0000000000401034 in populate_data (arg=0x7fffffffe5d8) at Queue.c:19
19 var->arr1[var->arr2[iG]] = iG;
及其回溯是:
#0 0x0000000000401034 in populate_data (arg=0x7fffffffe5d8) at Queue.c:159
#1 0x00007ffff7bc6971 in start_thread () from /lib/libpthread.so.0
#2 0x00007ffff792292d in clone () from /lib/libc.so.6
#3 0x0000000000000000 in ?? ()
但是,我无法纠正错误。
非常感谢Anyhelp。
答案 0 :(得分:1)
请在start_thread
中显示主叫代码。
似乎可能是堆栈和/或内存分配错误,结构非常大(假设32位int
s为8 MB)并且可能会溢出一些堆栈限制。
更可能的是,它已超出范围,这就是必须显示调用步骤的原因。
答案 1 :(得分:0)
我不知道你是否更改了_my_struct中数组的名称以隐藏它们的目的(公司机密信息,也许?),但是如果这样的话实际上你将你的阵列命名为什么,我只是建议你给他们命名一些对你有用的东西,当有人在4年后阅读你的代码时,他们会有一些希望遵循你的初始化循环&amp;了解发生了什么。您的循环变量iG
也是如此。
我的下一个评论/问题是,你为什么要开始一个线程来初始化主线程堆栈上的这个结构?一旦初始化了哪个线程将使用该结构?或者你打算使用其他线程来使用它?你有没有任何机制(互斥?信号量?)来确保其他线程不会开始使用数据,直到你的初始化线程初始化它为止?哪种问题引起了疑问,为什么你要打扰一个单独的线程来初始化它呢?您可以通过直接从main()调用populate_data()来初始化它,甚至不必担心同步,因为在完成初始化之前,您甚至不会启动任何其他线程。如果您正在多核计算机上运行,那么当main()继续运行时,您可以通过触发该单独的线程进行初始化来获得一些小的好处。做其他的东西,但从你的结构的大小(不是很小,但也不是很大)似乎这种好处将是非常微小的。如果你在一个核心上运行,你根本就不会获得并发利益;由于上下文切换开销,你只是浪费时间从另一个线程开始执行它;在一个单一的环境中,你最好直接从main()调用populate_data()。
接下来的评论是,你的_my_struct并不大,所以它不会自行炸掉你的堆栈。但它也很小。如果你的应用程序总是只需要这个结构的一个副本,也许你应该把它变成一个全局变量或一个文件范围变量,所以它不会占用堆栈空间。
最后,对你的实际错误............
我没有费心去尝试破译你的神秘循环代码,但是valgrind告诉我你有一些依赖于未初始化位置的条件:
~/test/so$ valgrind a.out
==27663== Memcheck, a memory error detector
==27663== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==27663== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==27663== Command: a.out
==27663==
==27663== Thread 2:
==27663== Conditional jump or move depends on uninitialised value(s)
==27663== at 0x8048577: populate_data (so2.c:34)
==27663== by 0x593851: start_thread (in /lib/libpthread-2.5.so)
==27663== by 0x4BDA8D: clone (in /lib/libc-2.5.so)
==27663==
==27663== Conditional jump or move depends on uninitialised value(s)
==27663== at 0x804868A: populate_data (so2.c:40)
==27663== by 0x593851: start_thread (in /lib/libpthread-2.5.so)
==27663== by 0x4BDA8D: clone (in /lib/libc-2.5.so)
我的so2.c第34行与上面代码发布中的第9行相对应。 我的so2.c第40行与上面代码发布中的第15行相对应。
如果我在populate_data()的顶部添加以下内容,这些valgrind错误就会消失:
memset(arg,0,sizeof(_my_struct_t));
(我修改了你的结构定义如下:)
typedef struct _my_struct { int pArr[21]; ......... } _my_struct_t;
现在只是因为添加memset()调用会使错误消失并不一定意味着你的循环逻辑是正确的,它只是意味着现在这些位置被认为是&#34;初始化&#34;由valgrind。如果在初始化循环开始时在这些位置具有全零是您的逻辑需要的,那么应该修复它。但是你需要自己验证这是否是正确的解决方案。
BTW ......有人建议使用calloc()来获得一个归零分配(而不是使用脏堆栈空间)......这也可以工作,但是如果你想让populate_data()变得万无一失,那你就是&#39 ; ll将内存归零而不是调用者,因为(假设您喜欢初始化逻辑),populate_data()依赖于它被清零,main()不应该这样做关心它是否是。无论如何都不是一件大事。