代码之家  ›  专栏  ›  技术社区  ›  Jamie Keeling

从lpvoid-c强制转换为结构

  •  2
  • Jamie Keeling  · 技术社区  · 14 年前

    我正在编写一个简单的控制台应用程序,它允许我从通过我提供的参数传递的一组参数创建多个线程。

    DWORD WINAPI ThreadFunc(LPVOID threadData)
    {
    }
    

    我将它们打包到一个结构中,并将它们作为参数传递到CreateThread方法中,并尝试通过将它们从lpvoid强制转换为与我的结构相同的类型来解包它们。

    我不知道如何在获取结构之后将其强制转换为结构,以便在方法本身中使用它,我尝试了各种组合(示例附加),但它不会编译。

    结构:

    #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”转换为“data”

    正如您所看到的,我已经实现了一种循环处理许多消息的方法,我正在尝试使事情稍微高级一点,并添加一些进一步的功能。

    7 回复  |  直到 14 年前
        1
  •  9
  •   Scott Smith    14 年前

    好吧,首先,这会爆炸:

    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!
                            ... );
    

    您可能希望传递指针的值(指针指向的结构的地址):

    // 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;
        // ...
    }
    
        2
  •  4
  •   CB Bailey    14 年前

    首先,只创建指向结构而不是结构本身的指针,然后使用未初始化的指针。

    struct Data *tData;
    
    tData->threads = numThreads;
    tData->messages = 3;
    tData->delay = 1000;
    

    您需要创建一个结构。如果创建线程的函数将在线程完成之前退出,那么您需要动态地创建它。例如

    struct Data *tData = malloc(sizeof *tData);
    

    然后,您应该确保在其他某个适当的点释放结构,如果不在其他地方使用,则在线程函数的末尾释放。

    然后你试着把 LPVOID 结构的参数,其中传递的是指向结构指针的指针。参数的大小不足以按值传递整个结构。您可能只想传入一个指向结构的指针(传入 tData 而不是 &tData CreateThread 然后你可以从 拉普拉斯 指向结构的指针。(因为这是C,不需要强制转换,您应该避免不必要的强制转换-不正确的强制转换可以掩盖真正的错误。)

    例如

    struct Data *tData = threadData;
    
        3
  •  3
  •   Ben Zotto sberry    14 年前

    lpvoid作为指向结构的指针而不是结构本身的指针传入。所以你需要这样的东西:

    struct Data * ptData = (struct Data *)threadData;
    

    然后您需要使用 -> 操作员:

    blahblah = ptData->messages;
    

    然而。在填充结构时,还缺少为其分配的存储空间,因为您使用的指针没有任何备用内存。你需要 malloc 结构。您应该阅读一下C语言中的内存管理。 this one 谈论结构)

        4
  •  1
  •   JaredPar    14 年前

    您正试图强制转换指针值( LPVOID 等于 void* )变为非指针值。这是不允许的。相反,您需要将其转换为不同的指针值,例如 struct Data* .

    尝试以下操作

    struct Data* pData = (struct Data*)threadData;
    
        5
  •  0
  •   Robert    14 年前

    将createThread函数中的数据强制转换为lpvoid

    hThread = CreateThread(
                            NULL,       // lpThreadAttributes (default)
                            0,          // dwStackSize (default)
                            ThreadFunc, // lpStartAddress
                            (LPVOID)tData,     // lpParameter
                            0,          // dwCreationFlags
                            &threadId   // lpThreadId (returned by function)
                           )
    

    同样在threadfunc中,数据应该是一个数据*

    如果你去定义lpvoid,你会发现它只是指向一个void的指针。因此,由于TData已经是一个指针,所以不需要指针的地址。

        6
  •  0
  •   Seva Alekseyev    14 年前

    替换为:

    struct Data *tData = (struct Data*)threadData; 
    
        7
  •  0
  •   Luca Rocchi    14 年前

    代码中还有其他错误…t数据似乎未分配..另外,您使用&address运算符传递它,因此您传递的是指针的地址,而不是指针。可能当你得到指针并使用它时,你会得到一个访问冲突