Jump to content

NumericArrayResize


Recommended Posts

#include "extcode.h"

BOOL WINAPI DllMain(HANDLE handle,

DWORD dwFunction,

LPVOID lpNot)

{

return TRUE;

}

_declspec (dllexport) int trial(int **arr)

{

MgErr err = NumericArrayResize(iL,1,(UHandle*)&arr,10);

if(err == noErr)

{

//(*arr)[0] = 10;

for(int i=1;i<10;i++)

(*arr)= i+1;

return 2;

}

return 4;

}

This is the code I am trying with, but the application is crashing again n again and my VI application is showing the array size ZERO.

But since the return type which I am getting is 2, means the function is getting executed.

During my search I came to know that the array in LV is like "First 32 Bytes for array length and other for data means n+4 bytes for n unsigned-8 bit data".

So when I am de-commenting the comment, my VI program is executing well and my VI is showing the array size 10. (Is it the write way to allocate memory???? or is it a BUG??)

NOW the main question where is the problem???

1) IS NumericArraySize not allocating the required memory (if this is the case then why MgErr == noErr ??)

2) Is there something else which I am missing????

Edited by prashant_bhutani
Link to comment

_declspec (dllexport) int trial(int **arr){	MgErr err = NumericArrayResize(iL,1,(UHandle*)&amp;arr,10);

It has been almost a decade since I've done any C-based NI stuff, but this line strikes me as odd. You're passing the address of arr to NumericArrayResize (that is an int*** cast to a UHandle*) which will be somewhere in your call stack. If this memory is manipulated, a crash would be one of the better things you can hope for. Do you maybe have an extra level of indirection in that statement?

Link to comment

#include "extcode.h"

BOOL WINAPI DllMain(HANDLE handle,

DWORD dwFunction,

LPVOID lpNot)

{

return TRUE;

}

_declspec (dllexport) int trial(int **arr)

{

MgErr err = NumericArrayResize(iL,1,(UHandle*)&arr,10);

if(err == noErr)

{

//(*arr)[0] = 10;

for(int i=1;i<10;i++)

(*arr)= i+1;

return 2;

}

return 4;

}

I assume you call the trial() function from the LabVIEW diagram using a Call Library Node. In that case you'll have to configure the parameter to be an Array passed as Handle and the function prototype will look like this.

typedef struct {

int32 dimSize;

int32 elm[1];

} **MyLabVIEWArrayHandle;

_declspec (dllexport) int trial(MyLabVIEWArrayHandle arr)

{

MgErr err = NumericArrayResize(iL, 1, (UHandle*)&arr, 10);

if(err == noErr)

{

........

Now you can go on but need of course to make sure to:

1) not exceed array elm[9] as the array does only contain 10 elements

2) make sure to assign the dimSize element the right value (for instance 10) before returning to the caller

Link to comment

_declspec (dllexport) int trial(int **arr){	MgErr err = NumericArrayResize(iL,1,(UHandle*)&amp;arr,10);

It has been almost a decade since I've done any C-based NI stuff, but this line strikes me as odd. You're passing the address of arr to NumericArrayResize (that is an int*** cast to a UHandle*) which will be somewhere in your call stack. If this memory is manipulated, a crash would be one of the better things you can hope for. Do you maybe have an extra level of indirection in that statement?

HI there!

Lets assume this line of code is causing the application to crash....

THEN why this application runs well after de-commenting the comment.......

This was not meant to insult anyone as I believe that my code could be wrong

BUT I cannot believe someone until he gives me a reason which is applicable to whole program not for just one case.

I assume you call the trial() function from the LabVIEW diagram using a Call Library Node. In that case you'll have to configure the parameter to be an Array passed as Handle and the function prototype will look like this.

typedef struct {

int32 dimSize;

int32 elm[1];

} **MyLabVIEWArrayHandle;

_declspec (dllexport) int trial(MyLabVIEWArrayHandle arr)

{

MgErr err = NumericArrayResize(iL, 1, (UHandle*)&arr, 10);

if(err == noErr)

{

........

Now you can go on but need of course to make sure to:

1) not exceed array elm[9] as the array does only contain 10 elements

2) make sure to assign the dimSize element the right value (for instance 10) before returning to the caller

Hi,

I am passing a null array as a parameter from LV but when I am looking at the indicator, it is not showing any result even for values/elements less than 10.....

If i pass an array with some elements, the indicator is showing values upto those corresponding elements only......

one last thing is using (*arr)[0]=10 is a good idea???

Link to comment

No offense taken...I'm just saying that looks wrong, but it has been a long time since I've used both C and LabVIEW at the same time.

Your function declares arr as an int**. NumericArrayResize is expecting a handle, but instead you're providing an int*** (by passing it &arr). Sure you cast to a UHandle* so the compiler won't complain, but they are most certainly not compatible and not the same. I don't know exactly what a UHandle is, but I expect an array handle should have information on the size, rank, as well as the obvious array contents, and I suspect other private info as well...

Link to comment

No offense taken...I'm just saying that looks wrong, but it has been a long time since I've used both C and LabVIEW at the same time.

Your function declares arr as an int**. NumericArrayResize is expecting a handle, but instead you're providing an int*** (by passing it &arr). Sure you cast to a UHandle* so the compiler won't complain, but they are most certainly not compatible and not the same. I don't know exactly what a UHandle is, but I expect an array handle should have information on the size, rank, as well as the obvious array contents, and I suspect other private info as well...

Lets see it this way.....

arr is a pointer to a pointer (**arr)....

so I need to cast it to UHandle** but then it will not be appropriate as handle is to/for point/handle pointers....

Now see what (UHandle*)&arr is (or better say try to) doing...

&arr is pointing to 0th element of array and (UHandle*) is casting that pointer to appropriate type so that it can be identified by LV..

please correct me if I am thinking in a wrong way

@rolfk

please tell me where is it getting wrong???

The situation is like as I said in one of my previous post::

1) NO output on passing NULL array (but the return value is 2)

2) Passing initialized array but result is up to those elements of initialized array only.

I am attaching the snapshot of VI that I am using.

Edited by prashant_bhutani
Link to comment

Hi,

I have changed the code a bit and the new one is

_declspec (dllexport) int trial(int **arr)

{

MgErr err = NumericArrayResize(iL,1,(UHandle*)&arr,10);

if(err == noErr)

{

for(int i=1;i<20;i++)

(*arr)= i;

return 2;

}

return 4;

}

Now if I pass an initialized array of elements less than 20.......

then EXPECTED (after reading so much documentations and forums) output should be crashing of LV

due to corruption of its memory in shared library(DLL)

BUT strangely the output array is showing me elements upto the initialized elements and still no sign of breakdown

CAN anyone explain me the reason for this? or have I read a lot that it corrupted my memory??

Link to comment

[quote name='prashant_bhutani' date='24 May 2010 - 06:50 PM' timestamp='1274723458'

I am passing a null array as a parameter from LV but when I am looking at the indicator, it is not showing any result even for values/elements less than 10.....

If i pass an array with some elements, the indicator is showing values upto those corresponding elements only......

one last thing is using (*arr)[0]=10 is a good idea???

Look you can go on as long as you want to insist that a LabVIEW array handle is simply just an int **. And it will keep crashing because it is NOT!

A LabVIEW array handle is a pointer to a pointer to a structure that contains as many int32 as the array has dimensions, and where the actual size of each dimension is stored, followed directly by the actual array data inlined into this structure. Unless you do it exactly like this your C code will try to treat it in a very different way than what LabVIEW gives you.

Or you pass the array as C array pointer. Then it is simply a C pointer and NumericArrayResize() has absolutely nothing to do with it.

There is no other option in between these two

Now if I pass an initialized array of elements less than 20.......

then EXPECTED (after reading so much documentations and forums) output should be crashing of LV

due to corruption of its memory in shared library(DLL)

BUT strangely the output array is showing me elements upto the initialized elements and still no sign of breakdown

CAN anyone explain me the reason for this? or have I read a lot that it corrupted my memory??

Illegal access doesn't always have to crash immediately. Its effects can vary from an immediate crash, to a delayed crash, to a crash only when you exit LabVIEW to no crash at all, but some data in LabVIEW could be corrupted so either LabVIEW suddenly gives you somewhere seemingly bad results or if you save your VIs after that they might be corrupted beyond repair.

The immediate crash only happens if the illegal memory access happens beyond any currently allocated memory for the process, the delayed happens if you overwrite LabVIEW data that it will try to access sooner or later

NumericArrayResize() does work properly on your int** pointer since it is in fact a handle that is passed into your C function from LabVIEW, despite your incorrect C datatype in your function prototype, so NumericArrayResize() can operate on it with no problem. The possible crash could however happen after index 10 already in your example because you resized the handle to 10. If you pass in a longer array then it likely will not crash before it passes over the original length, because a resize to a smaller size will often be done inplace to save CPU time as otherwise the entire data has to be copied. But there is no guarantee that such a resizing will always happen inplace and you should never assume it does.

But the returned array in LabVIEW should really show empty since you overwrite the first integer with its index which is 0 and that happens to be the length element in the LabVIEW array handle. LabVIEW only looks at the dimSize element to determine the length of an array. And if it says 0 in there it takes it as zero element array! It does not matter if you have NumericArrayResized that handle to 2GB or whatever, if dimSize is 0 the array is 0 length as far as the LabVIEW compiler is concerned and finito.

If it shows you still all the initialized array elements then you do something different than you have told us so far and you will need to show us the entire C code AND the VI in order for us to give you any more details

Link to comment

Look you can go on as long as you want to insist that a LabVIEW array handle is simply just an int **. And it will keep crashing because it is NOT!

A LabVIEW array handle is a pointer to a pointer to a structure that contains as many int32 as the array has dimensions, and where the actual size of each dimension is stored, followed directly by the actual array data inlined into this structure. Unless you do it exactly like this your C code will try to treat it in a very different way than what LabVIEW gives you.

Or you pass the array as C array pointer. Then it is simply a C pointer and NumericArrayResize() has absolutely nothing to do with it.

There is no other option in between these two

Illegal access doesn't always have to crash immediately. Its effects can vary from an immediate crash, to a delayed crash, to a crash only when you exit LabVIEW to no crash at all, but some data in LabVIEW could be corrupted so either LabVIEW suddenly gives you somewhere seemingly bad results or if you save your VIs after that they might be corrupted beyond repair.

The immediate crash only happens if the illegal memory access happens beyond any currently allocated memory for the process, the delayed happens if you overwrite LabVIEW data that it will try to access sooner or later

NumericArrayResize() does work properly on your int** pointer since it is in fact a handle that is passed into your C function from LabVIEW, despite your incorrect C datatype in your function prototype, so NumericArrayResize() can operate on it with no problem. The possible crash could however happen after index 10 already in your example because you resized the handle to 10. If you pass in a longer array then it likely will not crash before it passes over the original length, because a resize to a smaller size will often be done inplace to save CPU time as otherwise the entire data has to be copied. But there is no guarantee that such a resizing will always happen inplace and you should never assume it does.

But the returned array in LabVIEW should really show empty since you overwrite the first integer with its index which is 0 and that happens to be the length element in the LabVIEW array handle. LabVIEW only looks at the dimSize element to determine the length of an array. And if it says 0 in there it takes it as zero element array! It does not matter if you have NumericArrayResized that handle to 2GB or whatever, if dimSize is 0 the array is 0 length as far as the LabVIEW compiler is concerned and finito.

If it shows you still all the initialized array elements then you do something different than you have told us so far and you will need to show us the entire C code AND the VI in order for us to give you any more details

Thanks rolf for so much of valuable information.

BTW, I am not rewriting first element to zero as I am starting loop from i=1.

I am attaching the zip file containing all my code and VI.

I hope it will give you more insight in my problem.

structure_passing.zip

Link to comment

Thanks rolf for so much of valuable information.

BTW, I am not rewriting first element to zero as I am starting loop from i=1.

I am attaching the zip file containing all my code and VI.

I hope it will give you more insight in my problem.

Read my post and try to understand it. Also make use of the right click popup option on the Call Library Node!!

There you will see that your function prototypes are simply way off as they are now

Your header prototypes should more look like this:

#ifndef STRUCTURE_H#define STRUCTURE_H#include "extcode.h"typedef struct {	int32 dimSize;	int32 elm[1];} IntArrRec, **IntArrHdl;#if defined(__cplusplus) || defined(__cplusplus__) extern "C" {#endifBOOL WINAPI DllMain(HANDLE handle,					DWORD,					LPVOID);_declspec (dllexport) int trial(IntArrHdl);_declspec (dllexport) int string_to_char_array(char *); // passing as CStr frm LabVIEW_declspec (dllexport) int string_to_char_aray_as_handle(LStrHandle); //passing string as an array handle#if defined(__cplusplus) || defined(__cplusplus__) }#endif#endif

The "#if defined(__cplusplus) || defined(__cplusplus__)" preprocessor defines will prevent the compiler from decorating your function names with the useless C++ parameter signature.

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.