CWindow RC 23

Started by José Roca, October 03, 2016, 03:04:12 PM

Previous topic - Next topic

José Roca

Finally, in your faster & version, if I'm not wrong you're creating memory leaks.

You allocate a buffer


pNewBuffer = allocate((ust1.m_BufferLen + ust2.m_BufferLen + 1) * sizeof(wstring))


and you return a string


RETURN DWSTR(cast(ubyte ptr, pNewBuffer), ust1.m_BufferLen + ust2.m_BufferLen)


constructed using this code


ResizeBuffer(size1)
m_BufferLen = len1
if len1 + 1 > size1 THEN m_BufferLen = size1 - 1
memcpy(m_pBuffer , cast(any ptr, pub), m_BufferLen * 2)
' Mark the end of the string with a double null
m_pBuffer[m_BufferLen] = 0


and pNewBuffer is never freed.


Marc Pons

#61
sorry Jose you are wrong, pNewBuffer is deallocated by the normal DWSTR destructor

check the code ,used  with the & constructor we dont put  size1 var ;   so  size1 = -1  ; so you  enter in the second condition
as you can see if you add the lines to print "here 1";"here 2";"here 3" on the constuctor
PRIVATE CONSTRUCTOR DWSTR (BYREF pub AS UBYTE PTR, BYREF len1 AS LONG, BYREF size1 AS LONG = -1) '****
   DWSTR_DP("+++BEGIN- DWSTR CONSTRUCTOR UBYTE - " & WSTR(pub))               
IF size1 = 0 THEN
this.ResizeBuffer(m_GrowSize)
print "here 1"
elseif size1 < 0 THEN ' we enter here with  my & operator
this.m_BufferLen = len1
this.m_pBuffer = cast(wstring ptr, pub)
this.m_Capacity = len1 + 1
print "here 2"
ELSE
ResizeBuffer(size1)
m_BufferLen = len1
if len1 + 1 > size1 THEN m_BufferLen = size1 - 1
memcpy(m_pBuffer , cast(any ptr, pub), m_BufferLen * 2)
' Mark the end of the string with a double null
m_pBuffer[m_BufferLen] = 0
print "here 3"
END IF
   DWSTR_DP("-END- DWSTR CONSTRUCTOR UBYTE - " & WSTR(this.m_pBuffer))
END CONSTRUCTOR


that means the pointer is not copied to another mem  , it is just affected to m_pBuffer and when the destructor will act the m_pBuffer ( so in fact the original pNewBuffer) will be deallocated normally

it would be even faster if we could avoid the following LET action wich reallocate again ( for nothing)
i've tried to avoid the LET after but it is too complex for the benefit...

see on your nice debug trace system
QuoteOPERATOR & DWSTR :  WSTRING & DWSTR
+++BEGIN- DWSTR CONSTRUCTOR UBYTE - 3361376
here 2
-END- DWSTR CONSTRUCTOR UBYTE - 3361376
DWSTR LET DWSTR
DWSTR Clear
DWSTR Add DWSTR - LEN = 26
DWSTR AppendBuffer 0 26
--END - DWSTR AppendBuffer 26
***DWSTR DESTRUCTOR - buffer: 3361376

DWSTR &  new operator : same or faster than de-referenced solution
DWSTR CAST BYREF AS WSTRING - buffer: 3359768

Marc Pons

#62
completing the analyse :
QuoteUsing the FB string data type, we can do:
   DIM s AS STRING = "Test string"
   DIM p AS ZSTRING PTR = STRPTR(s)
   PRINT *p

Using CWSTR, we can do:
   DIM cws AS CWSTR = "Test string"
   DIM p AS WSTRING PTR = *cws
   PRINT *p

Using DWSTR, we can do:
   DIM dws AS DWSTR = "Test string"
   DIM pw AS WSTRING PTR = STRPTR(dws)
   PRINT *pw

                  That is exactly as the first one

we can also use the ** shortcut:
   DIM cws AS CWSTR = "Test string"
   PRINT **cws 'explicit double dereferenced
   ' or better  PRINT cws     ' because the implicit cast : byref to wstring

let's see with DWSTR
   DIM dws AS DWSTR = "Test string"
   PRINT *dws     'explicit dereferenced       noticed only 1 dereferecing
   'or better  PRINT dws  'same implicit cast: byref to wstring

that does for CWSTR
   DIM p AS WSTRING PTR = *cws
   PRINT *p

with normal string
   DIM ps AS ZSTRING PTR = strptr(s)
   PRINT *ps

and for DWSTR
   DIM pdw AS WSTRING PTR = strptr(dws)   ' a agree  strptr is longuer to type than * 
   PRINT *pdw

        but with DWSTR : 
           STRPTR working as with normal string to get the WSTRING ptr
           VARPTR working as with normal string to get the DWSTR ptr, or even just : @DWSTR 

2 different approchs
     CWSTR more c++  behaviour , coherent with all your framework and their types construction
     DWSTR a dynamic WSTRING  with almost "native"  BASIC type behaviour

my purpose from the begining : to have a dynamic Wstring and use it as we do with normal string, without speed cost (or very marginal)

Marc Pons

#63
QuoteThe CodePage is not useless. Just because you can build a CWSTR concatenating strings with different code pages, doesn't mean that you have to.
If you really need the use of a code page, you will have to use a function like AfxUcode, that allows to specify the code page. Free Basic should add an optional code page parameter to STR and WSTR.

m_codePage on CWSTR type :
why is it needed to store it, as the resulting CWSTR can be a mix with possible different codepage ?
what the benefit for CWSTR , or for the output to convert it back if it could be completly wrong ?

AfxUcode is very good function , i've tried to overload the wstr with it but without sucess

in the reverse , converting CWSTR to ansi, the only way i can considere
    is defining explicitly the codepage if you want a specific one,
    or use the normal system codepage
so what the need for storing the codepage information into CWSTR, if we can't trust that info ,
and in fact it is not even needed , your afxAcode (if correct) is playing perfectly the role


José Roca

I think that it is evident: it is used by the Add and Insert functions if you pass an ansi string and don't specify a code page when you call them. Which benefit will you have removing it?

José Roca

#65
> my purpose from the begining : to have a dynamic Wstring and use it as we do with normal string

I almost never use what you call a "normal" string, which is everything but normal, because its format is proprietary. The only use that I have for it is as a buffer for binary content if I don't want to allocate the memory using Allocate.

I ill see what I can do with the & operator.

José Roca

You seem only interested in CWSTR, but I'm also interested in CBSTR, and what you suggest for CWSTR can't be applied to CBSTR, and I like consistency. If I have removed it from the posted framework is only because nobody is willing to test, so I will keep my research about COM programming with FB private. Doesn't make sense to inundate this forum with new code if only I use it.

José Roca

#67
> it would be even faster if we could avoid the following LET action wich reallocate again ( for nothing)
i've tried to avoid the LET after but it is too complex for the benefit...

It does not reallocate. It is called to assign the result to the CWSTR in "cws =". The problem with functions that return strings is that they must be copied to the target variable. The fastest way is to pass a variable by reference, as most Windows API functions do, but it is much less comfortable to use.


Marc Pons

Jose,

just to let you know, my DWSTR , is posted on the FreeBasic Forum
http://www.freebasic.net/forum/viewtopic.php?f=17&t=24070&start=15#p226207

intended to work with Windows & Linux

Thanks for all your support, I will see if some interrest on the subject.

Marc