Originally posted by Barry Andrews:
I know the call that fails on the C++ side. I just make 1 call to some legacy C++ code which has been around for years and still works today.
Ok, let me get this correct. So, the line which generates this exception calls a legacy C++ function that you do not have the code for?
Can you trace the problem down to the actual call to Windows API?
To this legacy method I pass the 2 pointers which were receieved from the Java side. So I come to the conclusion that the pointers are invalid. The question is why?
Not neccesarily. Let me try to give an overview of how this error code is usually used. In Windows , many of the APIs provided by windows look like this
void GetXXX(byte* lpBuffer, DWORD sizeOfBuffer, DWORD* requiredSize);
Before you make the call to this function, you are suppossed to allocate the correct number of bytes to lpBuffer, and provide the size of the buffer in sizeOfBuffer. So, a rudimentary way of calling this function would be
The first thing the API will do is compare the sizeOfBuffer parameter with the actual size of XXX. If the size is too less, then it will throw ERROR_INSUFFICIENT_BUFFER(which is what you are getting). If sizeOfBuffer is enough, it will fill the buffer with contents of XXX
So, whenever you get this error, there could be 2 things happenning
a) the memory allocated to your pointer is less than the API wants
b) pointers and other data on the heap is corrupted
You need to rule out a) before you can investigate b). It could happen that this error occurs ony under certain conditions, and the reason you are not seeing it 100% of the time is because you don't recreate the same conditions 100% of the time.
It also depends on the data you are trying to get. For example, one popular Windows API that is used to list the printers on the network uss the above technique. Now, in many big intranet systems, the number of printers on the network are not constant. People turn their printers on and off all the time, and at any given time the number of printers change. So, at one meoment the network would have 100 printers, and you will allocate memory for 100 printers, but in the meantime another printer turns on, and now you will get the ERROR_INSUFFICIENT_BUFFER error
I know this is an odd way of doing things
Investigating memory corruption
Interestingly, someone in the Java Forums - Native Methods said he uses long instead of int to handle passing pointers around in JNI. So I gave that a try and sure enough it did help. It works MUCH better now, but there still is some issue because it does not work 100% of the time.
Is that long or jlong? long is not the same as jlong. In Windows, jlong is _int64 and long is the same as jint. In Java int is 4 bytes. A C++ pointer is also 4 bytes. I don't have a problem with typecasting a C++ pointer to a jint rather than a jlong, unless there is some justification
I do have problems with typecasting C++ pointer to anything else other than a C++ pointer. Generally, I avoid passing C++ pointers back and forth between Java and C++, precisely because of the problems that you are facing. When you are typecasting a pointer to any other integral type, you might run into problems that occur because of type-unsafe operations. Being able to fundamentally type cast on type to another is one of the biggest flaws of C++ and should be avoided. However, I don't want to go into the details of this because changing this might affect your application drastically.