Author Topic: _msize discussion  (Read 8606 times)

jcfuller

  • Sr. Member
  • ****
  • Posts: 415
    • View Profile
_msize discussion
« on: February 21, 2020, 04:58:56 PM »
Kevin,
  Why would _msize not work for dynamic allocated strings.
James

Code: [Select]
$NOMAIN
$NOINI
$ONEXIT "VSC.BAT $FILE$ -m64 con"


Function main() As Integer
Dim A$ * 2048
Dim B$
If sizeof(A$) = 8 Then
? _msize(A$)
End If
? sizeof(B$)
Pause
End Function


MrBcx

  • Administrator
  • Hero Member
  • *****
  • Posts: 2392
    • View Profile
Re: _msize discussion
« Reply #1 on: February 21, 2020, 06:23:34 PM »
A frightening coincidence just occurred ...

I was just about to upload this snippet:

Code: [Select]

DIM Buffer$ * 100  ' BCX adds an extra 256 bytes for a total of 356 bytes

DIM b AS INTEGER

b = _msize (Buffer$)

PRINT b


I discovered _msize on this page:

https://stackoverflow.com/questions/1281686/determine-size-of-dynamically-allocated-memory-in-c

and confirmed it here:

https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/msize?view=vs-2017

https://docs.microsoft.com/en-us/cpp/c-runtime-library/compatibility?view=vs-2017


NOTES:

_msize is non-standard and not portable, so if that's an issue for you, best to avoid using it.

My example (above) compiles and runs using Pelles, LccWin32, and Mingw



MrBcx

  • Administrator
  • Hero Member
  • *****
  • Posts: 2392
    • View Profile
Re: _msize discussion
« Reply #2 on: February 21, 2020, 06:31:51 PM »
Kevin,
  Why would _msize not work for dynamic allocated strings.
James


James,

To further my thoughts on _msize, there must be a number of uses for this function.

It's too new to me and I need to think about it, experiment with it, and consider
where it might appropriately be incorporated in BCX. 


Preserving classic BASIC syntax will always top my list.

Your example hints at an important aspect about _msize.

If you pass a static variable instead of a dynamic variable, LccWin32 and G++
return -1 but Pelles results in CRT: unhandled exception (main) -- terminating

Not good.

Any use of _msize needs to be done carefully.
« Last Edit: February 21, 2020, 06:41:29 PM by MrBcx »

Robert

  • Hero Member
  • *****
  • Posts: 1256
    • View Profile
Re: _msize discussion
« Reply #3 on: February 22, 2020, 03:59:04 AM »
Kevin,
  Why would _msize not work for dynamic allocated strings.
James


James,

To further my thoughts on _msize, there must be a number of uses for this function.

It's too new to me and I need to think about it, experiment with it, and consider
where it might appropriately be incorporated in BCX. 


Preserving classic BASIC syntax will always top my list.

Your example hints at an important aspect about _msize.

If you pass a static variable instead of a dynamic variable, LccWin32 and G++
return -1 but Pelles results in CRT: unhandled exception (main) -- terminating

Not good.

Any use of _msize needs to be done carefully.

MrBCX might want to have a look at this thread,  "Failing code", on the Pelle's C Forum from 2015

https://forum.pellesc.de/index.php?topic=6615.0

and this thread, "PellesC _msize fix" at

https://forum.pellesc.de/index.php?topic=6622.0

I haven't tested them to see if they're still relevant but I thought you may like to have a look.

MrBcx

  • Administrator
  • Hero Member
  • *****
  • Posts: 2392
    • View Profile
Re: _msize discussion
« Reply #4 on: February 22, 2020, 07:31:00 AM »
Thanks for the links Robert ...

I appreciate the effort Frankie put towards the issue but it still seems like an unstable kludgefest to me.
I extracted and tested his last reworking of _msize ( which he renamed _fmsize ) and found it (gracefully) failed.
I submitted a _msize tweak under Feature Request on Pelles forum last evening.  I don't expect it to go anywhere.

I toyed with the following this morning:
Code: [Select]

C_DECLARE FUNCTION My_msize LIB "msvcrt.dll" ALIAS "_msize" ( PV as void ptr) AS INTEGER

DIM Buffer$  * 100  ' BCX adds an extra 256 bytes for a total of 356 bytes

DIM b AS INTEGER

b = My_msize (Buffer$)

PRINT b



Pelles, LccWin32, and Mingw all compile it. 

Output from the .Exe's is another matter ...

Mingw
356


Pelles C
-1


LccWin32
 72756


I initially used DECLARE but changed to C_DECLARE as _msize uses the cdecl calling convention. 
The only obvious thing that changed was that Pelles no longer throws an unhandled exception but it still fails to report the size.

One opinion that resonates with me is, if one wants to reliably know the current allocation of an object,
one must save that information when the allocation is successfully invoked ( malloc(), calloc(), realloc() ... )

Sorry to say, the _msize air is slipping away from beneath my wings.
« Last Edit: February 22, 2020, 11:01:36 AM by MrBcx »

jcfuller

  • Sr. Member
  • ****
  • Posts: 415
    • View Profile
Re: _msize discussion
« Reply #5 on: February 22, 2020, 10:59:37 AM »
Kevin,
  VC also goes to lala land when trying to _msize an invalid pointer

James

Robert

  • Hero Member
  • *****
  • Posts: 1256
    • View Profile
Re: _msize discussion
« Reply #6 on: February 22, 2020, 01:33:54 PM »
Here's an ancient (circa 2005) _msize Microsoft MSDN C test example

Code: [Select]

/* Realloc.c: This program allocates a block of memory for
 * buffer and then uses _msize to display the size of that
 * block. Next, it uses realloc to expand the amount of
 * memory used by buffer and then calls _msize again to
 * display the new amount of memory allocated to buffer.
 */

#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>

int main( void )
{
   long *buffer;
   size_t size;

   if( (buffer = (long *)malloc( 1000 * sizeof( long ) )) == NULL )
      exit( 1 );

   size = _msize( buffer );
   printf( "Size of block after malloc of 1000 longs: %u\n", size );

   /* Reallocate and show new size: */
   if( (buffer = (long *)realloc( buffer, size + (1000 * sizeof(long)) )) ==  NULL )
      exit( 1 );
   size = _msize( buffer );
   printf( "Size of block after realloc of 1000 more longs: %u\n", size );

   free( buffer );
   exit( 0 );
   return 0;
}

/* Expected Output
 *
 * Size of block after malloc of 1000 longs: 4000
 * Size of block after realloc of 1000 more longs: 8000
 *
 */


my system outputs

Microsoft Visual Studio 2019 32 bit

Size of block after malloc of 1000 longs: 4000
Size of block after realloc of 1000 more longs: 8000

Microsoft Visual Studio 2019 64 bit

Size of block after malloc of 1000 longs: 4000
Size of block after realloc of 1000 more longs: 8000

Pelle's C 32 9.0 32 bit

Size of block after malloc of 1000 longs: 4003
Size of block after realloc of 1000 more longs: 8006


Pelle's C 32 9.0 64 bit

Size of block after malloc of 1000 longs: 4007
Size of block after realloc of 1000 more longs: 8014


Nuwen 17.1 64 bit

Size of block after malloc of 1000 longs: 4000
Size of block after realloc of 1000 more longs: 8000

MinGW64 32 bit

Size of block after malloc of 1000 longs: 4000
Size of block after realloc of 1000 more longs: 8000

MinGW64 64 bit

Size of block after malloc of 1000 longs: 4000
Size of block after realloc of 1000 more longs: 8000

Embarcadero bcc32.exe 32 bit

Size of block after malloc of 1000 longs: 4140
Size of block after realloc of 1000 more longs: 8236


Embarcadero bcc32.exe 64 bit

realloc.cpp:20:11: error: use of undeclared identifier '_msize'
   size = _msize( buffer );

jcfuller

  • Sr. Member
  • ****
  • Posts: 415
    • View Profile
Re: _msize discussion
« Reply #7 on: February 22, 2020, 01:38:37 PM »
Kevin,
  Why will this not work:
Test var with sizeof: BufferSize = sizeof(var)
If 4 or 8 then BufSize = _msize(var)
else you have Buffersize
  fgets(var,BufferSize,FP1)

James

Robert

  • Hero Member
  • *****
  • Posts: 1256
    • View Profile
Re: _msize discussion
« Reply #8 on: February 22, 2020, 02:14:06 PM »
Kevin,
  Why will this not work:
Test var with sizeof: BufferSize = sizeof(var)
If 4 or 8 then BufSize = _msize(var)
else you have Buffersize
  fgets(var,BufferSize,FP1)

James

Example please?

jcfuller

  • Sr. Member
  • ****
  • Posts: 415
    • View Profile
Re: _msize discussion
« Reply #9 on: February 22, 2020, 02:46:26 PM »
Robert,
  I was not able to figure out how or  where to do it.
Any changes in the Emit_FileIOProcs blew up the  bcx compile.
I can do it in my cppfixups function after the fact but.....
James

Robert

  • Hero Member
  • *****
  • Posts: 1256
    • View Profile
Re: _msize discussion
« Reply #10 on: February 22, 2020, 03:17:07 PM »
Robert,
  I was not able to figure out how or  where to do it.
Any changes in the Emit_FileIOProcs blew up the  bcx compile.
I can do it in my cppfixups function after the fact but.....
James

Hi James:

Yes, blew up ... I had the same problem checking out "sizeof". Have to go through the C code and examine the input data type for each and EVERY fgets call to find the culprit. I started yesterday with "Src" which feeds into fgets and is

Code: [Select]
  Src=(char*)calloc(256+cMaxSrcLen ,1);
That one's O.K. but that took some time and figuring that it would take several hours to check the input for each and EVERY fgets, my enthusiasm fell off the cliff.

And that is not counting the ones that are not exposed but hiding in unused functions etc,

Robert

  • Hero Member
  • *****
  • Posts: 1256
    • View Profile
Re: _msize discussion
« Reply #11 on: February 22, 2020, 03:20:46 PM »
Robert,
  I was not able to figure out how or  where to do it.
Any changes in the Emit_FileIOProcs blew up the  bcx compile.
I can do it in my cppfixups function after the fact but.....
James

Hi James:

Yes, blew up ... I had the same problem checking out "sizeof". Have to go through the C code and examine the input data type for each and EVERY fgets call to find the culprit. I started yesterday with "Src" which feeds into fgets and is

Code: [Select]
  Src=(char*)calloc(256+cMaxSrcLen ,1);
That one's O.K. but that took some time and figuring that it would take several hours to check the input for each and EVERY fgets, my enthusiasm fell off the cliff.

And that is not counting the ones that are not exposed but hiding in unused functions etc,

The most difficult part of the problem is that bc,exe compiles as expected but doesn't run properly. I guess I don't have to tell you this, but I thought maybe you didn't even get that far.

jcfuller

  • Sr. Member
  • ****
  • Posts: 415
    • View Profile
Re: _msize discussion
« Reply #12 on: February 22, 2020, 04:15:59 PM »

Robert,
  I Put a "If IsBcx" around the Emit_FileIOProcs so it would only see the new code for  an app but that blewup too.

This is the what I want and I can do it in my cppfixup
Basic
Code: [Select]
Function LoadTheBuffer(f As const char Ptr) As BOOL
    Dim As stdstr ss
    Dim sLine$
    OPEN f FOR INPUT AS FP1
    While Not EOF(FP1)
        Line Input FP1,sLine$
        ss = sLine$
        gsvBuffer.push_back(ss)
    Wend
    Function = 0
End Function
I think this is right! Translated
Code: [Select]
    while(!EoF(FP1))
    {
        sLine[0] = 0;
    if(sizeof(sLine) == 4 || sizeof(sLine) == 8 )
        {
        fgets(sLine, _msize(sLine), FP1);
        }
    else
    {
        fgets(sLine, sizeof(sLine), FP1);
    }

        if(sLine[strlen(sLine) - 1] == 10)sLine[strlen(sLine) - 1] = 0;
        ss = sLine;
        gsvBuffer.push_back(ss);
    }

Robert

  • Hero Member
  • *****
  • Posts: 1256
    • View Profile
Re: _msize discussion
« Reply #13 on: February 22, 2020, 05:21:38 PM »

Robert,
  I Put a "If IsBcx" around the Emit_FileIOProcs so it would only see the new code for  an app but that blewup too.

This is the what I want and I can do it in my cppfixup
Basic
Code: [Select]
Function LoadTheBuffer(f As const char Ptr) As BOOL
    Dim As stdstr ss
    Dim sLine$
    OPEN f FOR INPUT AS FP1
    While Not EOF(FP1)
        Line Input FP1,sLine$
        ss = sLine$
        gsvBuffer.push_back(ss)
    Wend
    Function = 0
End Function
I think this is right! Translated
Code: [Select]
    while(!EoF(FP1))
    {
        sLine[0] = 0;
    if(sizeof(sLine) == 4 || sizeof(sLine) == 8 )
        {
        fgets(sLine, _msize(sLine), FP1);
        }
    else
    {
        fgets(sLine, sizeof(sLine), FP1);
    }

        if(sLine[strlen(sLine) - 1] == 10)sLine[strlen(sLine) - 1] = 0;
        ss = sLine;
        gsvBuffer.push_back(ss);
    }

If you have it working in a stand alone app, please do a timing test using a large file, say 100 megabytes, comparing your suggested changes and the existing BCX fixed size. I would wager that _msize-ing and sizeof-ing will be twenty times slower. You think?

Robert

  • Hero Member
  • *****
  • Posts: 1256
    • View Profile
Re: _msize discussion
« Reply #14 on: February 23, 2020, 12:19:45 AM »

Robert,
  I Put a "If IsBcx" around the Emit_FileIOProcs so it would only see the new code for  an app but that blewup too.

This is the what I want and I can do it in my cppfixup
Basic
Code: [Select]
Function LoadTheBuffer(f As const char Ptr) As BOOL
    Dim As stdstr ss
    Dim sLine$
    OPEN f FOR INPUT AS FP1
    While Not EOF(FP1)
        Line Input FP1,sLine$
        ss = sLine$
        gsvBuffer.push_back(ss)
    Wend
    Function = 0
End Function
I think this is right! Translated
Code: [Select]
    while(!EoF(FP1))
    {
        sLine[0] = 0;
    if(sizeof(sLine) == 4 || sizeof(sLine) == 8 )
        {
        fgets(sLine, _msize(sLine), FP1);
        }
    else
    {
        fgets(sLine, sizeof(sLine), FP1);
    }

        if(sLine[strlen(sLine) - 1] == 10)sLine[strlen(sLine) - 1] = 0;
        ss = sLine;
        gsvBuffer.push_back(ss);
    }

Hi James:

I modified the BCX 7.4.5 translator so in the C output code, instead of

Code: [Select]

      fgets(Src, 1048576,SourceFile);
 

it output

Code: [Select]

          if(sizeof(Src) == 4 || sizeof(Src) == 8 )
          {
           fgets(Src, _msize(Src),SourceFile);
          }
          else
          {
           fgets(Src, sizeof(Src),SourceFile);
          }


On the third recompile, using VS 2019 cl.exe, the .cpp output was truncated at line 4159.

I then tried increasing the output buffer size by adding 256 and still truncation at line 4159.