NO

Author Topic: Change valist with an array of args  (Read 1599 times)

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 1612
Change valist with an array of args
« on: February 19, 2016, 02:36:49 pm »
This is the modified code that still holds the former one, commented out, for reference purpose.
« Last Edit: February 23, 2016, 10:41:46 am by frankie »

Offline jcfuller

  • Member
  • *
  • Posts: 35
Re: Change valist with an array of args
« Reply #1 on: February 22, 2016, 12:14:02 pm »
frankie,
  I found a piece of code that fails using your CreateArr code.
It is really non-real world code in my opinion as there is no data to preserve,
but it does compile and run as a 32bit app with PellesC, VS 2015, TDM-GCC-32, Tiny C 9.2.6
It fails with all of them when compiled as a 64bit app except Tiny C 9.2.6 64bit.
If we remove the "preserve" and use just: redim buffer$[arr_size] it is fine.
Thank you for your help,

James

"c" with preserve
Code: [Select]
buffer = (char**)CreateArr (buffer, sizeof(char), 1, 2, dimensions);
"c" without preserve
Code: [Select]
buffer = (char**)CreateArr (buffer, sizeof(char), 0, 2, dimensions);

This is the basic code that produces the attached "c".
Code: [Select]
    dim dynamic buffer$[10]
    dim num_lines as integer
    dim arr_size as integer
    arr_size = 10
    num_lines = 0
    for num_lines = 1 to 100
        if num_lines >= arr_size then
            print "*** growing from: " & STR$(arr_size) & " to: " & STR$(arr_size + 10);
            arr_size += 10
            redim preserve buffer$[arr_size]
            print " *** grown"
        end if
    next
    Pause   

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 1612
Re: Change valist with an array of args
« Reply #2 on: February 22, 2016, 01:33:08 pm »
Ok got it.
This should be the main reason for bad working.
The code adds two dummy elements at the end of the array and set them to 0 to be used as an end of array mark. The original code used this line to set them to 0:
Code: [Select]
*(((int *)vp)) = 0;
In this way only 4 bytes of an 8 bytes 64bits pointer are set to 0, the remaining keeps the trash that they contained. Anyway it works on machines having int of same size of pointers. But on 64bits machine this is not the case...  8)
I replaced it with this code:
Code: [Select]
*(((void **)vp)) = NULL;
That correctly set a full size pointer.
You may try this fix also on the original code using variadic functions, and I think it will come back to life!  ;D
Let me know.

EDIT the patch can be also:
Code: [Select]
*vp = NULL;
Because vp is already defined as void **vp;.
« Last Edit: February 22, 2016, 04:25:47 pm by frankie »

Offline jcfuller

  • Member
  • *
  • Posts: 35
Re: Change valist with an array of args
« Reply #3 on: February 22, 2016, 02:53:57 pm »
frankie,
  THANK YOU, THANK YOU
We did need your change away from the variadic function along with this one.
So far all is well.

James

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 1612
Re: Change valist with an array of args
« Reply #4 on: February 22, 2016, 03:19:05 pm »
You're welcome.

Offline jcfuller

  • Member
  • *
  • Posts: 35
Re: Change valist with an array of args
« Reply #5 on: August 02, 2016, 07:17:48 pm »
frankie,
  I'm back.
The attached uses the CreateArr function you developed which I have been using with no apparent issues.
I wanted to determine how big the array was so I used _msize to find the index count of the array. It reports 2 more than I requested?? Compiled as a 64bit app. Same results with VC .

James


Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 1612
Re: Change valist with an array of args
« Reply #6 on: August 03, 2016, 11:34:56 am »
[EDIT]
Hello James
I rewrote the CreateArr function to avoid the use of variable number of arguments, but I retained the original algorithm for array allocation. As I already explained in my previous posts (see above) The code reserves 2 additional elements at the end of the array as a kind of marker.
Now if you look in the code you will see (my comment)
Code: [Select]
void *CreateArr(void *a, int elem_size, int update, int num_dims, size_t *args)
{
size_t s, s1, s2;
void **vp;
size_t *marker;
marker = args;
s = *marker++;
s2 = s + 2; //Frankie: It always allocates 2 elements more than requested
if (num_dims == 1)
{
if (update && a)
a = realloc(a, s2 * elem_size);
else
a = calloc(s2, elem_size);
return a;
}
else if (update && a)
{
s1 = 0;
          .......

If you replace the line with the following:
Code: [Select]
    s2 = s;
You'll get the correct answer. But... it will broke the multidimensional code!
Moreover you cannot use _msize to get the number of elements, because the dynamically created array is not a standard one when dimensions>1. I.e. following code:
Code: [Select]
void DoIt (void)
{
    AFX_ANCHORPROPERTY  *skAnchor = 0;
    {
        size_t dimensions[2] = {5, 5};
        skAnchor = (AFX_ANCHORPROPERTY*)CreateArr (skAnchor, sizeof(AFX_ANCHORPROPERTY), 0, 2, dimensions);
    }
    printf("%s%.15G\n", "UBOUND-> ", (double)( _msize ( skAnchor) / sizeof ( AFX_ANCHORPROPERTY)));
    if (skAnchor) {
        DestroyArr((void **)skAnchor, 1, 1);
        skAnchor = NULL;
    }
}
Will print 1 instead of 10. This is because multidimensional arrays are built as array of pointers to array of values. In the current case you'll get an array of 2 pointers to 2 different monodimensional arrays each holding 5 values. You get 1 because the dimension of the bidimensional pointers array divided by the size of the structure is 1.
« Last Edit: August 03, 2016, 12:15:41 pm by frankie »

Offline jcfuller

  • Member
  • *
  • Posts: 35
Re: Change valist with an array of args
« Reply #7 on: August 03, 2016, 12:54:27 pm »
Thank you for your explanation. My old brain is not as good at retaining as it used to be :)
Now, would s2 = s work on single dimension arrays only?

James

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 1612
Re: Change valist with an array of args
« Reply #8 on: August 03, 2016, 01:36:28 pm »
Yes it should work, but on multidimensional arrays CreateArr will crash, you will not be able anymore to create multidimensional arrays.