.NET Framework - Memory corruption with interop call

Asked By Fredo
28-Jul-08 01:14 PM
First of all, I apologize for cross-posting. I posted this on the
framework.interop group as well, but haven't received a response yet, so I
thought I'd try here...

I'm trying to write an app that perfroms some work using the CUDA SDK (for
programming the nVidia GPU).

One of the first methods I wrote is simply to query information about the
CUDA devices (video cards).

The code is very straightforward, but I'm getting an error that indicates
some sort of memory corruption and I'm not really sure how it's happening. I
don't think it's CUDA related, I think it's just something wrong with my
interop calls. Maybe the arrays? The exception I'm getting happens during
the return from GetCUDADeviceProperties (see implementation below and
comment on line that throws exception). It appears to be happening in the
marshalling back of the data. The exception is:

in NeuralNetTimingTest.exe
Additional information: Attempted to read or write protected memory. This is
often an indication that other memory is corrupt."

When I step through the code, GetCUDADeviceProperties() appears to properly
set the fields in the CUDADevice structure.

Here's the relevant code:

From C#:

* The device information structure is this:

[StructLayout(LayoutKind.Sequential)]
public struct CUDADevice
{
public int deviceID;
public int totalMem;
public int numMultiProcessors;
public int numCores;
public int constantMem;
public int sharedMem;
public int registersPerBlock;
public int warpSize;
public int numThreadsPerBlock;
public int[] maxBlockDimensions;
public int[] maxGridDimensions;
}

* The DllImport is:

[DllImport("NeuralNetCUDALib")]
extern static bool GetCUDADeviceProperties(ref CUDADevice device);

* And the C# code that calls it is:

// Allocate the device structure
CUDADevice dev = new CUDADevice();
// Allocate the two arrays
dev.maxBlockDimensions = new int[3];
dev.maxGridDimensions = new int[3];

// Device to query
dev.deviceID = 0;
GetCUDADeviceProperties(ref dev);

* The non-CUDA C++ code is:
* From the .h, the C++ side of the CUDADevice structure

typedef struct tagCUDADevice
{
int deviceID;
int totalMem;
int numMultiProcessors;
int numCores;
int constantMem;
int sharedMem;
int registersPerBlock;
int warpSize;
int numThreadsPerBlock;
int maxBlockDimensions[3];
int maxGridDimensions[3];
} CUDADevice;

extern "C" bool GetCUDADeviceProperties(CUDADevice *pDevice)
{
if (GetDeviceCount() <= 0)
{
return false;
}

if (!QueryDeviceInfo(pDevice->deviceID,
pDevice->totalMem,
pDevice->numMultiProcessors,
pDevice->numCores,
pDevice->constantMem,
pDevice->sharedMem,
pDevice->registersPerBlock,
pDevice->warpSize,
pDevice->numThreadsPerBlock,
pDevice->maxBlockDimensions,
pDevice->maxGridDimensions))
{
return false;
}
return true; // Exception happens during this return!
}


* And the actual CUDA code is:

bool QueryDeviceInfo(int deviceNum,
int &totalMem,
int &numMultiProcessors,
int &numCores,
int &constantMem,
int &sharedMem,
int ®istersPerBlock,
int &warpSize,
int &numThreadsPerBlock,
int *maxBlockDimensions,
int *maxGridDimensions)
{
cudaDeviceProp prop;
cudaGetDeviceProperties(&prop, deviceNum);
totalMem = (int) prop.totalGlobalMem;
numMultiProcessors = (int) prop.multiProcessorCount;
numCores = (int) numMultiProcessors * 8;
constantMem = (int) prop.totalConstMem;
sharedMem = (int) prop.sharedMemPerBlock;
registersPerBlock = (int) prop.regsPerBlock;
warpSize = (int) prop.warpSize;
numThreadsPerBlock = (int) prop.maxThreadsPerBlock;
maxBlockDimensions[0] = (int) prop.maxThreadsDim[0];
maxBlockDimensions[1] = (int) prop.maxThreadsDim[1];
maxBlockDimensions[2] = (int) prop.maxThreadsDim[2];
maxGridDimensions[0] = (int) prop.maxGridSize[0];
maxGridDimensions[1] = (int) prop.maxGridSize[1];
maxGridDimensions[2] = (int) prop.maxGridSize[2];
return true;
}
UnmanagedType.ByValArray
(1)
GetCUDADeviceProperties
(1)
NeuralNetCUDALib
(1)
N6YxDVnZ2dnUVZ
(1)
AccessViolationException
(1)
LayoutKind.Sequential
(1)
UnmanagedType
(1)
TagCUDADevice
(1)
  Nicholas Paldino [.NET/C# MVP] replied...
28-Jul-08 01:51 PM
Fredo,

It looks like your declaration for the CUDADevice is incorrect.  You
have to specify that the arrays are passed by value in the structure of the
array:

[StructLayout(LayoutKind.Sequential)]
public struct CUDADevice
{
public int deviceID;
public int totalMem;
public int numMultiProcessors;
public int numCores;
public int constantMem;
public int sharedMem;
public int registersPerBlock;
public int warpSize;
public int numThreadsPerBlock;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public int[] maxBlockDimensions;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public int[] maxGridDimensions;
}

--
- Nicholas Paldino [.NET/C# MVP]
- mvp@spam.guard.caspershouse.com
  Fredo replied...
28-Jul-08 02:10 PM
You nailed it. Thanks Nicholas. Don't know what I'd do without you and
Jon....
Create New Account
help
I define the following struct : [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct IncomingData { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)] public byte[] Buffer; } And get the output from 'GetData' into the byte array and wanted something like this : [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct IncomingData { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)] public byte[] Buffer; public string Field1 { get { return ParseStr(Buffer, 0, 10);}} public be converted to numeric values) : [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct IncomingData { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)] public byte[] Buffer; public single Field1 { get { return ParseStr(Buffer, 0, 10);}} public Where 'IncomingData' is the following : [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct IncomingData { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)] public byte[] Buffer; public single Field1 { get { return ParseStr(Buffer, 0, 10);}} public
break on and try and look at it is properties, intellisense gives me a 'System.AccessViolationException' even though the correct data appears to be being returned to the browser, it I the calling app, intellisense reports '((MyCOMDllTypes.IMyCOMInterface) (_MyCOMObject)).Token' threw an exception of type 'System.AccessViolationException' + base {"Attempted to read or write protected memory. This is often an indication that other memory is corrupt."} System.SystemException {System.AccessViolationException} Noted. Sorry - I am a bit slow on all this - steep learning curve (for me no longer exists, it will fail. Somehow. How specifically I do not know, but an AccessViolationException seems like as reasonable an outcome as any other. :) There is nothing in the examples string p_key); FYI . . . when I step the code, and check the thread state when the AccessViolationException occurs, intellisense tells me that the thread isAlive and the ThreadState is running. That sounds
I know the size of the buffer before it is sent? TIA, Asaf C# Discussions UnmanagedType.ByValArray (1) LayoutKind.Sequential (1) Marshal.SizeOf (1) UnmanagedType (1) LayoutKind (1) CharSet (1) Marshal (1 The format is: [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] public class TEST { [MarshalAs(UnmanagedType.ByValArray)] public byte[] Buffer; } where buffer is allocated later. The Interop system knows to send the
System.AccessViolationException was unhandled .NET Framework MS Visual Studio 2008 Version 3.5 and my OS is Threading.ThreadHelper.ThreadStart() InnerException: C# Discussions System.Threading.ThreadHelper.ThreadStart (1) Visual Studio 2008 (1) AccessViolationException (1) System.Windows.Forms (1) UnsafeNativeMethods (1) Vista (1) ExecutionContext (1) ContextCallback (1) Too little symptom of that. Again, impossible to say without a proper code example. Pete keywords: System.AccessViolationException, was, unhandled description: MS Visual Studio 2008 Version 3.5 and my OS is Vista
excepcion 'System.AccessViolationException' .NET Framework Hola a todo / as: Necesito ayuda porque llevo atascada unos dias con esto para evitarme este error, me aparece el siguiente: Excepci?n no controlada del tipo 'System.AccessViolationException' en AG.exe Informaci?n adicional: Intento de leer o escribir en la memoria protegida voy arrancando, pero mira que me cuesta :). Menos gracias a vosotros. Saludos. keywords: excepcion, 'System.AccessViolationException' description: Hola a todo / as: Necesito ayuda porque llevo atascada unos dias con esto y