从LPVOID铸造结构 - C
我正在写一个简单的控制台应用程序,它将允许我通过通过我提供的参数传递的一组参数创建一些线程。从LPVOID铸造结构 - C
DWORD WINAPI ThreadFunc(LPVOID threadData)
{
}
我包装他们进入一个结构和将它们作为参数传入的CreateThread的方法,并试图通过他们铸造的同类型从LPVOID我的结构解压它们。
我不知道如何将它转换到结构后,所以我可以在方法本身使用它,我试过各种组合(例如attatched),但它不会编译。
结构:
#define numThreads 1
struct Data
{
int threads;
int delay;
int messages;
};
电话方法:
HANDLE hThread;
DWORD threadId;
struct Data *tData;
tData->threads = numThreads;
tData->messages = 3;
tData->delay = 1000;
// Create child thread
hThread = CreateThread(
NULL, // lpThreadAttributes (default)
0, // dwStackSize (default)
ThreadFunc, // lpStartAddress
&tData, // lpParameter
0, // dwCreationFlags
&threadId // lpThreadId (returned by function)
);
我尝试:
DWORD WINAPI ThreadFunc(LPVOID threadData)
{
struct Data tData = (struct Data)threadData;
int msg;
for(msg = 0; msg<5; msg++)
{
printf("Message %d from child\n", msg);
}
return 0;
}
编译器错误:
错误C2440: '类型转换':不能从'LPVOID'转换为'数据'
正如你所看到的,我已经实现了一种方法来循环遍历一些消息,我试图让事情稍微更先进,并添加一些更多的功能。
OK,对于初学者来说,这是要炸毁:
struct Data *tData;
tData->threads = numThreads;
tData->messages = 3;
tData->delay = 1000;
...因为你已经创建类型“指针结构”的变量,但你有没有初始化指向任何东西的指针。 tData
未初始化,所以您正在写入野指针。
你可能想是这样的:
// Allocate memory for the struct on the heap
struct Data *tData = malloc(sizeof(struct Data));
// Initialize _all_ fields of the struct (malloc won't zero fill)
tData->threads = numThreads;
tData->messages = 3;
tData->delay = 1000;
其次,您要传递地址tData
(在内存中的位置,其中tData
变量所在),而不是位置内存tData
指向:
// Create child thread
hThread = CreateThread(...,
&tData, // OOPS - ADDRESS OF THE POINTER VARIABLE ITSELF!
...);
你可能想通过指针的值(struct的地址,它指向):
// Create child thread
hThread = CreateThread(...,
tData, // Value of the pointer
...);
当您收到您的回调函数的结构的地址,将它转换回原来的指针到结构类型,取消引用,并享受:
DWORD WINAPI ThreadFunc(LPVOID threadData)
{
struct Data *tData = (struct Data *)threadData;
int numMessages = tData->messages;
// ...
}
感谢您的详细解释,我来自C#背景,所以指针等概念对我来说是相当新的。 – 2010-03-11 18:55:03
您正试图将指针值(LPVOID
等效于void*
)转换为非指针值。这是不允许的。相反,您需要将其转换为不同的指针值,例如struct Data*
。
请尝试以下
struct Data* pData = (struct Data*)threadData;
在CreateThread函数你要把你的数据作为LPVOID
hThread = CreateThread(
NULL, // lpThreadAttributes (default)
0, // dwStackSize (default)
ThreadFunc, // lpStartAddress
(LPVOID)tData, // lpParameter
0, // dwCreationFlags
&threadId // lpThreadId (returned by function)
)
而且ThreadFunc中的数据应该是数据*
如果你去definitaion LPVOID你会看到它只是一个指向void的指针。所以既然tData已经是一个指针了,你不需要指针的地址。
替换:
struct Data *tData = (struct Data*)threadData;
的LPVOID即将作为一个指针结构,而不是结构本身。所以,你想要的东西,如:
struct Data * ptData = (struct Data *)threadData;
然后你需要与运营商->
访问字段:
blahblah = ptData->messages;
但是。由于您使用的是没有任何后备内存的指针,因此您在填充结构时也缺少为该结构分配的存储空间。你需要malloc
的结构。你应该阅读C中的内存管理。(在许多其他链接中,this one谈论结构)
感谢您的解释 – 2010-03-11 18:54:38
首先,您只创建一个指向结构而不是结构本身的指针,然后使用未初始化的指针。
struct Data *tData;
tData->threads = numThreads;
tData->messages = 3;
tData->delay = 1000;
您需要创建一个结构。如果创建线程的函数将在线程完成之前退出,那么您需要动态创建它。例如
struct Data *tData = malloc(sizeof *tData);
您应该确保结构,然后在适当的点在其他地方释放,或许在线程函数结束时,如果它不是在别处使用。
然后,您尝试将LPVOID
参数强制转换为结构体,其中您传递的是指向结构体的指针的指针。该参数不会足够大,无法通过值传递整个结构。你可能只想传递一个指向你的结构体的指针(通过tData
而不是&tData
到CreateThread
然后你可以从LPVOID
初始化到你的结构体的指针(因为这是C,所以不需要强制转换,你应该避免不必要的强制转换 - 不正确的人可能会掩盖真正的错误)
如
struct Data *tData = threadData;
感谢您的回答 – 2010-03-11 18:55:40
有在你的代码其他错误...... TDATA似乎没有分配..你也与&地址运营商通过它,所以你。正在传递指针的地址而不是指针。可能当你得到指针并使用它时,你会得到一个AccessViolati在
我已经标记了正确的答案,但底层的问题是你不明白指针或动态分配,所以你还没准备好进行线程化。 – 2010-03-11 18:38:24
我的理解程度,我会在给出答案后再读。 – 2010-03-11 18:54:00