【发布时间】:2016-09-13 07:03:24
【问题描述】:
我有一个程序,我创建了 4 个线程,但只等待第一个线程[0]。 线程只是打印一些内容。但是当我执行以下程序时,我会得到访问冲突 有时。
#include<Windows.h>
#include <stdio.h>
#include<tchar.h>
#define KEYLEN 8
#define DATALEN 56
typedef struct _RECORD{
CHAR key[KEYLEN];
TCHAR data[DATALEN];
}RECORD;
#define RECSIZE sizeof(RECORD)
typedef RECORD *LPRECORD;
typedef struct _THREADARG{
DWORD iTh;
LPRECORD lowRecord; // pointer to Low record
LPRECORD highRecord;
} THREADARG, *PTHREADARG;
static int KeyCompare(LPCTSTR, LPCTSTR);
static DWORD WINAPI SortThread(PTHREADARG pThArg);
static DWORD nRec; // Total Number of records to be sorted
static HANDLE *pThreadHandle;
DWORD Options (int argc, LPCTSTR argv [], LPCTSTR OptStr, ...);
int _tmain(int argc, LPTSTR argv[]){
HANDLE hFile, mHandle;
LPRECORD pRecords = NULL;
DWORD lowRecordNum, nRecTh,numFiles, iTh;
LARGE_INTEGER fileSize;
BOOL noPrint;
int iFF, iNP;
PTHREADARG threadArg;
LPTSTR stringEnd;
iNP = 1;
iFF = iNP + 1;
numFiles = _ttoi(argv[iNP]);
if (argc <= iFF)
_tprintf (_T ("Usage: sortMT [options] nTh files."));
/* Open the file and map it */
hFile = CreateFile (argv[iFF], GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE)
_tprintf (_T ("Failure to open input file."));
if (!SetFilePointer(hFile, 2, 0, FILE_END) || !SetEndOfFile(hFile))
_tprintf (_T ("Failure position extend input file."));
mHandle = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL);
if (NULL == mHandle)
_tprintf (_T ("Failure to create mapping handle on input file."));
/* Get the file size. */
if (!GetFileSizeEx (hFile, &fileSize))
_tprintf (_T ("Error getting file size."));
nRec = (DWORD)fileSize.QuadPart / RECSIZE;
nRecTh = nRec / numFiles;
threadArg = malloc (numFiles * sizeof (THREADARG)); /* Array of thread args. */
pThreadHandle = malloc (numFiles * sizeof (HANDLE));
/* Map the entire file */
pRecords = MapViewOfFile(mHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (NULL == pRecords)
_tprintf (_T ("Failure to map input file."));
CloseHandle (mHandle);
/* Create the sorting threads. */
lowRecordNum = 0;
for (iTh = 0; iTh < numFiles; iTh++) {
threadArg[iTh].iTh = iTh;
threadArg[iTh].lowRecord = pRecords + lowRecordNum;
threadArg[iTh].highRecord = pRecords + (lowRecordNum + nRecTh);
lowRecordNum += nRecTh;
pThreadHandle[iTh] = (HANDLE)_beginthreadex (
NULL, 0, SortThread, &threadArg[iTh], CREATE_SUSPENDED, NULL);
}
/* Resume all the initially suspened threads. */
for (iTh = 0; iTh < numFiles; iTh++)
ResumeThread (pThreadHandle[iTh]);
/* Wait for the sort-merge threads to complete. */
WaitForSingleObject (pThreadHandle[0], INFINITE);
for (iTh = 0; iTh < numFiles; iTh++);
CloseHandle (pThreadHandle[iTh]);
//Sleep(3); // Un comment it and see no error.
UnmapViewOfFile(pRecords);
// Restore the file length
/* SetFilePointer is convenient as it's a short addition from the file end */
if (!SetFilePointer(hFile, -2, 0, FILE_END) || !SetEndOfFile(hFile))
_tprintf("Failure restore input file lenght.");
CloseHandle(hFile);
free (threadArg); free (pThreadHandle);
return 0;
}
DWORD WINAPI SortThread(PTHREADARG pThArg){
DWORD groupSize = 2, myNumber, twoToI = 1;
/* twoToI = 2^i, where i is the merge step number. */
DWORD_PTR numbersInGroup;
LPRECORD first;
myNumber = pThArg->iTh;
first = pThArg->lowRecord;
numbersInGroup = (DWORD)(pThArg->highRecord - first);
printf(" %d : %s \n",myNumber, pThArg->lowRecord );
return 0;
}
文件内容结构:
02d2d159. Record Number: 00000000.abcdefghijklmnopqrstuvwxyz X
f362711e. Record Number: 00000001.abcdefghijklmnopqrstuvwxyz X
ba957dff. Record Number: 00000002.abcdefghijklmnopqrstuvwxyz X
但是如果我在创建线程之后给一个 Sleep(N); 就没有问题了。! 所以我理解 main() 线程在子线程之前退出。但是当 main() 退出时,整个进程应该终止。不是吗? 那么访问冲突怎么可能呢?
为什么我访问冲突?
【问题讨论】:
-
你能把你的例子缩小到它仍然发生的地方并且没有任何不必要的东西吗?但可能发生的情况是,在内部清理内存时,您的线程仍在此全局内存上运行和操作。
-
在调用任何堆内存分配函数(malloc、calloc、realloc)时,始终检查 (!=NULL) 返回值以确保操作成功。
-
为了便于阅读和理解:1) 遵循公理:每行只有一个语句,并且(最多)每个语句一个变量声明。
-
最好将结构定义与使用该结构的
typedef定义分开
标签: c multithreading pointers