April 19, 2024, 05:50:20 PM

News:

Own IWBasic 2.x ? -----> Get your free upgrade to 3.x now.........


Access Violation

Started by ckoehn, February 07, 2010, 02:20:11 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

ckoehn

February 07, 2010, 02:20:11 PM Last Edit: February 07, 2010, 02:22:05 PM by ckoehn
What causes access violations?  I'll try to post the needed parts of the code (won't be able to post everything) to get some help.  If I miss something let me know what is needed.

I'm trying to make a print routine using ddoc that justifies the text on the page.  As far as I can tell ddoc is working OK.  It looks like I can't add 2 FLOATS together.  That is where the acccess violation occurs.  What is wrong?

SUB PrintSel()
Replace(sel,CHR$(13)+CHR$(10)," ~ ") 'turn CRLF into ~  (my routine, it works OK) sel[16000] is a global ISTRING
Split(sel," ") 'split sel into words (my routine, it works OK) words[4000] is a global STRING

prtFile=dpStartDoc(0,"Title","",DDOC_INCH,DDOC_PAPER_LETTER,DDOC_PORTRAIT,DDOC_SYSTEM_DEFAULT,DDOC_ZOOMFIT)

dpFont(prtFile, DDOC_FONTNORMAL, 14, RGB(0,0,0), "Times New Roman")
prtX=4.25f
prtY=0.5f
dpText(prtFile,prtX,prtY,DDOC_CENTER,"Title")
prtY+=0.4f
dpFont(prtFile, DDOC_FONTNORMAL, 10, RGB(0,0,0), "Times New Roman")
dpText(prtFile,prtX,prtY,DDOC_CENTER,GETSTRING(win,Files,GETSELECTED(win,Files)))
dpFont(prtFile, DDOC_FONTNORMAL, 11, RGB(0,0,0), "Times New Roman")
prtY+=.50
prtX=1.0
lSpc=dpTextWidth(prtFile," ")
FOR pi=1 TO maxspl
OneWord=words[pi]
IF (OneWord="~")
prtX=1f
prtY+=0.3f
IF prtY>10.25f
'print pgnum and new page
dpPageNo(prtFile,4.25,10.5,DDOC_CENTER,0)
dpNewPage(prtFile,DDOC_PAPER_LETTER,DDOC_PORTRAIT,DDOC_SYSTEM_DEFAULT)
prtY=1f
prtX=1f
dpFont(prtFile, DDOC_FONTNORMAL, 11, RGB(0,0,0), "Times New Roman")
ENDIF
'need to get spacing for next LINE
ELSE
txtWidth=0.0f
IF OneWord<>""
txtWidth=dpTextWidth(prtFile,OneWord)
ENDIF
STOP
txtWidth+=prtX   <----- ACCESS VIOLATION
IF (txtWidth>7.75f)
prtX=0.75f
prtY+=0.18f
IF prtY>10.25f
'print pgnum and new page
dpPageNo(prtFile,4.25,10.5,DDOC_CENTER,0)
dpNewPage(prtFile,DDOC_PAPER_LETTER,DDOC_PORTRAIT,DDOC_SYSTEM_DEFAULT)
prtY=1f
prtX=0.75f
dpFont(prtFile, DDOC_FONTNORMAL, 11, RGB(0,0,0), "Times New Roman")
ENDIF
'need to get spacing for next LINE
ENDIF
OneWord=words[pi]
dpText(prtFile,prtX,prtY,DDOC_LEFT,OneWord)
prtX=lSpc+txtWidth
ENDIF
NEXT pi
dpPageNo(prtFile,4.25,10.5,DDOC_CENTER,0)
dpEndDoc(prtFile,DDOC_END_VIEW+DDOC_END_DELETE)'DDOC_END_SPECIFIC_PRINTER

ENDSUB

fasecero

Maybe the cause is the STOP keyword itself.

This example can be debugged without any problem...


OPENCONSOLE
PRINT PrintSel()

DO:UNTIL INKEY$ <> ""
CLOSECONSOLE

END

SUB PrintSel()
STOP

float r=0.1
FOR j= 1 to 10
r+=0.1
NEXT j
RETURN r
ENDSUB


... but placing the STOP keyword inside the loop seems to generate access violations:


SUB PrintSel()
float r=0.1
FOR j= 1 to 10

STOP
r+=0.1
NEXT j
RETURN r
ENDSUB

ckoehn

Thanks for you input.

The reason the STOP is there is because the code wasn't functioning as expected.  The rows (prty) would never increment.  The comarison would never occur where it checked if it was the end of the line.

If I can find time today, I'm going to break it down to a bare minimum printout code and see if it works.

ckoehn

Just an update.  I have yet to make it work.  I found if I place a MESSAGEBOX one line below my IF statement,  it works fine for every row but the indented one.

I am very experienced in BASIC programming.  This program is not responding at all like would be expected.

I would need someone who has DDOC32.DLL to test it for me because I use the dpTextWidth command.  It returns a FLOAT value.

I will probably see what else I can find out about it before I give up and go somewhere else.  I really like the way EBASIC works though.

fasecero

I remember me having a similar trouble when returning a float from a dll.
Try changing the return type to DOUBLE (in the function declaration).

billhsln

You say it works ok except for the indented line.  Question:  is the indented line multiple spaces or tab characters?

My reasoning is, maybe txtWidth=dpTextWidth(prtFile,OneWord) is returning an invalid value?

Bill
When all else fails, get a bigger hammer.

ckoehn

fasecero:  Will try that today.  I put a DOUBLE in my program but I'm not sure if I changed the return value to a DOUBLE.   Will that return the correct value?

Bill:  It appears like it is returning a correct number.  Here was my logic.

The width of the paper is 8.5".  With a normal 3/4" margin that leaves 7" to fill with characters.  When a "return" (which is "~") is found make the left margin 1".

The current column position on the page is stored in prtX which is a FLOAT.

The current row position is stored in prtY which is a FLOAT.

Total up the word lengths until they are greater than the right magin which occurs at 7.75".

Divide the space left (7.75-word len) by the number of spaces needed.  This tells how much to inc the prtX before printing the next word.  This value also is a FLOAT.

So there is no tab.  Just setting prtX and prtY to where I want the next character placed.

Thanks,
Clint

ckoehn

fasecero:  Changing the return value to DOUBLE didn't work.  It has to be FLOAT.  That returns the correct value.

I attached my test code below.  If anyone can tell me what it is that is making me add the unnecessary additional code (remarked with <---) I'd like to hear about it.

This will only compile and work for someone who has installed DDOC32.dll.  I had to add:

DECLARE IMPORT, dpTextWidth(iHandle AS INT,zText as string),FLOAT

to the ddoc.inc file since it is a later addition to the DDOC32.DLL.  This function seems to work OK.  It is something with EB.

Thanks,
Clint

TonyMUK

When I have had this problem in the past I have found that upping the stack size on the compile options has generally fixed the problem. Don't know whether it will in your case but it is worth a try.
Check out www.arnoldchiari.co.uk. If you don't know what Arnold Chiari is you are very lucky.

ckoehn

Tony:  Thanks for your input.  That wasn't the answer either.  It made no difference.

Later,
Clint

sapero

February 09, 2010, 09:22:02 AM #10 Last Edit: February 09, 2010, 09:24:51 AM by sapero
Maybe you have declared the apis using bad callling convention? stdcall/cdecl or even other?
Check out dll2lib tool http://www.ionicwind.com/forums/index.php/topic,1361.0.html.

Load your dll to this tool, find and select dpTextWidth function, then click "__stdcall" button.
If the function will be renamed to _dpTextWidth@0, then it is cdecl (or fastcall), and you need to add the cdecl keyword in your .inc file:
declare cdecl import, dpTextWidth(.....)
If it will be renamed to _dpTextWidth@8, then it is for sure stdcall, and the declaration should be
declare import, dpTextWidth(.....)
_dpTextWidth@4 - thiscall.

To use this detection technique you should pick a function with three 32-bit arguments: (three*4=12)
_name@12 - stdcall
_name@8 - thiscall (one argument passed in register)
_name@4 - fastcall (two arguments passed in registers)
_name@0 - cdecl

Thiscall and fastcall are not directly supported in Ebasic.

ckoehn

Thanks sapero for looking at this. Will check it out and update this thread with what I find.  I was hoping you would look at this.

Thanks,
Clint

ckoehn

Here is the screen shot from your program.  If I understand you right, it is declared properly.

sapero

Yup, if dpTextWidth really takes two arguments, then it is stdcall, and the decoration in dll2lib should be @8.
I don't have DDOC32.DLL, and all I've found is an .exe version. Is there any demo or trial of this dll?

ckoehn


sapero

February 09, 2010, 02:57:30 PM #15 Last Edit: February 09, 2010, 04:16:53 PM by sapero
Found the dll in Watermark demo (?).
I can say, that dpTextWidth returns a float in EAX register (handled by ebasic), and in ST0 register (not handled by ebasic). You need to pop the value from floating point stack using a small inline asembly:

variable = dpTextWidth(...)
_asm
fstp dword[esp-4] ; or pop it to a temporary float variable: fstp dword[variableName]
_endasm

You need to append the _asm ... _endasm after all dp** functions, which returns a float or double.

If the variable is a global one (defined outside subroutines), you can 'fstp' directly into it:
dpTextWidth(...)
_asm
fstp dword[variable] ; use qword instead dword, if variable type is double.
_endasm



In your code:
txtWidth=dpTextWidth(g_prtFile,g_words[g_pi])

v1=txtWidth+prtX '<---- THE NEXT STATEMENT DOESN'T EXECUTE WITHOUT THIS, WHY?
IF (txtWidth+g_prtX)>7.75

Answer: the floating point stack is (was) constantly overflow'ed, because the return value in st0 was not popped.

Normally when f.p. stack overflow occurs, an exception is thrown. It is possible to mask FPU exceptions (ebasic is masking them).
You can reenable f.p. exceptions executing another inline assambly code:
word fpControlWord ' global variable
_asm
fstcw word[fpControlWord] ; load current control word
and word[fpControlWord],1111111111000000b ; enable all (6) exceptions - clear 6 LSB bits
fldcw word[fpControlWord] ; apply
_endasm

Exceptions (from left, last 6 bits) precision,underflow,overflow,divideBy0,denormalizedOperand,invalidOperation. Use 1 (mask) or 0 (enable) in the binary mask.

ckoehn

sapero,  Thanks a trillion.  There is no possible way I would have ever figured it out.  Yet I've always said, "When you know the answer the question isn't hard".  That's why some people don't appreciate the answers you give them. :)

Will try it but am sure it will work.

Thanks a bunch again.

Clint

LarryMc

Sapero, you never cease to amaze me! :o :o :o

Thanks for all the help you provide.

LarryMc
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library