使用 Win32 的多线程

Multiple Threads using Win32

我正在用 C 语言编写一个多线程 ASCII 字符计数器。当我将 NUM_THREADS 设置为 1 时,该程序按预期运行,但它会因任何其他数字而崩溃。这是我的第一个可变多线程作业,我以为我理解了一切,但我想我遗漏了一些东西。

这是我的资料:

#include <stdio.h>
#include <windows.h>

#define BUF_SIZE 65536
#define NUM_THREADS 2

struct ThreadInfo {
    char buffer[BUF_SIZE];
    int threadNum;
    int firstIndex;
    int lastIndex;
};


int char_count[NUM_THREADS][128];
int bytesRead = 0;

DWORD WINAPI countChars(struct ThreadInfo *threadInfo);

int main(int argc, char* argv[]){
    DWORD ThreadId[NUM_THREADS];
    HANDLE ThreadHandles[NUM_THREADS];
    struct ThreadInfo threadInfo;
    char buffer[BUF_SIZE];

    buffer[BUF_SIZE - 1] = '[=10=]';

    if(argc < 2){
        printf("Usage Error: Incorrect number of arguments.\n");
        printf("Usage: ASCIICount <file1>\n");
        return 1;
    }

    for(int i = 0; i < NUM_THREADS; i++){
        for (int j = 0; j < sizeof(char_count); j++) {
            char_count[i][j] = 0;
        }
    }

   HFILE file1 = CreateFile(argv[1], 
       GENERIC_READ,
       0,
       NULL,
       OPEN_EXISTING,
       FILE_ATTRIBUTE_NORMAL,
       NULL);

   if(file1 == INVALID_HANDLE_VALUE){
       printf("Error opening %s.\n", argv[1]);
       return 1;
   }

   ReadFile(file1, buffer, sizeof(buffer)-1, &bytesRead, NULL);

   strcpy(threadInfo.buffer, buffer);

   for (int i = 0; i < NUM_THREADS; i++) {
       threadInfo.threadNum = i;
       threadInfo.firstIndex = (i)*((bytesRead/NUM_THREADS));
       threadInfo.lastIndex = (i+1)*(bytesRead/NUM_THREADS) - 1;

       ThreadHandles[i] = CreateThread(
           NULL, //default security attributes
           0, // default stack size
           countChars, // thread function
           &threadInfo, // parameter to thread function
           0, // default creation flags
           &ThreadId[i]);
   }

   for (int i = 0; i < NUM_THREADS; i++) {
       if (ThreadHandles[i] != NULL) {
           // now wait for the thread to finish
           WaitForSingleObject(ThreadHandles[i], INFINITE);

          //close the thread handle
          CloseHandle(ThreadHandles[i]);
       }
   }

   printf("Buffer size: %d\n", sizeof(buffer));
   printf("Bytes read: %d\n", bytesRead);
   for (int i = 0; i < NUM_THREADS; i++) {
       for (int j = 0; j < 128; j++) {
           if (j < 33 || j == 127) {
               printf("%d, %#x, %d\n", j, j, char_count[i][j]);
           }
           else {
               printf("%d, %c: %d\n", j, j, char_count[i][j]);
           }
       }
   }
   return 0;
}

DWORD WINAPI countChars(struct ThreadInfo *threadInfo){
    char cur_char;
    for(int i = threadInfo->firstIndex; i < threadInfo->lastIndex; i++){
        cur_char = threadInfo->buffer[i];
        char_count[threadInfo->threadNum][cur_char]++;
    }
    return 0;
}

正如Jonathan Potter指出的那样

"Every thread will need its own ThreadInfo"