안녕하세요, 정수가 아닌 값으로 쓰는 중 찢어지는 int 및 float 예제가 필요합니다. 나는 이것을 재현 할 수 없다. 그것은 매우 드물거나 내가 잘못하고있는 어떤 것으로 보인다.non-atomics가 찢어 지도록하기
인쇄되지 않는 테스트 코드는 다음과 같습니다. 거기에 문제가 있습니까? 내가 찢어 트리거 할 수 있습니다
#include <windows.h>
#include <tchar.h>
#include <strsafe.h>
#define MAX_THREADS 64
#define BUF_SIZE 255
DWORD WINAPI MyThreadFunction(LPVOID lpParam);
void ErrorHandler(LPTSTR lpszFunction);
// Sample custom data structure for threads to use.
// This is passed by void pointer so it can be any data type
// that can be passed using a single void pointer (LPVOID).
typedef struct MyData {
int val1;
int val2;
} MYDATA, *PMYDATA;
int _tmain()
{
DWORD dwThreadIdArray[MAX_THREADS];
HANDLE hThreadArray[MAX_THREADS];
// Create MAX_THREADS worker threads.
for(int i=0; i<MAX_THREADS; i++)
{
// Allocate memory for thread data.
// Create the thread to begin execution on its own.
hThreadArray[i] = CreateThread(
NULL, // default security attributes
0, // use default stack size
MyThreadFunction, // thread function name
NULL, // argument to thread function
0, // use default creation flags
&dwThreadIdArray[i]); // returns the thread identifier
// Check the return value for success.
// If CreateThread fails, terminate execution.
// This will automatically clean up threads and memory.
if (hThreadArray[i] == NULL)
{
ErrorHandler(TEXT("CreateThread"));
ExitProcess(3);
}
} // End of main thread creation loop.
// Wait until all threads have terminated.
WaitForMultipleObjects(MAX_THREADS, hThreadArray, TRUE, INFINITE);
// Close all thread handles and free memory allocations.
for(int i=0; i<MAX_THREADS; i++)
{
CloseHandle(hThreadArray[i]);
}
return 0;
}
#pragma pack(push, 1)
struct Test
{
char x1;
char x1;
char x3;
int test;
char x4;
char x5;
};
Test* t = new Test(); //This is test code don't care about allocation or that it is a global.
#pragma pack(pop)
DWORD WINAPI MyThreadFunction(LPVOID lpParam)
{
HANDLE hStdout;
TCHAR msgBuf[BUF_SIZE];
size_t cchStringSize;
DWORD dwChars;
// Make sure there is a console to receive output results.
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
if(hStdout == INVALID_HANDLE_VALUE)
return 1;
static int thread = 0;
StringCchPrintf(msgBuf, BUF_SIZE, TEXT("Starting thread, %d\n"), ++thread);
StringCchLength(msgBuf, BUF_SIZE, &cchStringSize);
WriteConsole(hStdout, msgBuf, (DWORD)cchStringSize, &dwChars, NULL);
t->test = 1;
for (int i=0; i<1000000000;++i)
{
t->test = 1;
t->test = 10000;
t->test = 10000000;
int result = t->test;
if(result != 1 && result != 10000 && result != 10000000)
{
StringCchPrintf(msgBuf, BUF_SIZE, TEXT("Tearing occured = %d\n"), result);
StringCchLength(msgBuf, BUF_SIZE, &cchStringSize);
WriteConsole(hStdout, msgBuf, (DWORD)cchStringSize, &dwChars, NULL);
}
}
return 0;
}
void ErrorHandler(LPTSTR lpszFunction)
{
// Retrieve the system error message for the last-error code.
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL);
// Display the error message.
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
(lstrlen((LPCTSTR) lpMsgBuf) + lstrlen((LPCTSTR) lpszFunction) + 40) * sizeof(TCHAR));
StringCchPrintf((LPTSTR)lpDisplayBuf,
LocalSize(lpDisplayBuf)/sizeof(TCHAR),
TEXT("%s failed with error %d: %s"),
lpszFunction, dw, lpMsgBuf);
MessageBox(NULL, (LPCTSTR) lpDisplayBuf, TEXT("Error"), MB_OK);
// Free error-handling buffer allocations.
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
}
32 비트 액세스의 경우 Intel 플랫폼에서 재생성 할 수 없기 때문에 이것을 재현 할 수 없습니다. 원자 변수는 테스트하지 않은 다른 문제, 즉 원자 값에 대한 액세스 이전과 이후의 변경 사항의 가시성을 해결합니다. 예를 들어 메모리 울타리가없는 비 원자 32 비트 액세스를 사용하여 스핀 록을 구현 한 경우 문제가 발생합니다. –
인텔 플랫폼에서 찢어진 32 비트 읽기 또는 쓰기를 관찰하려면 최소한 캐시 라인 경계 또는 심지어 페이지 경계를 가로 지르는 정렬되지 않은 액세스가 필요합니다. 일반적으로 찢어진 32 비트 읽기 또는 쓰기는 인텔 플랫폼에서 일반적인 정렬로 발생하지 않을 것입니다. 어떤 상황에서 트리거 될 수 있는지 확실하지 않습니다. – mattnewport