Access Violation using strcpy
I am struggling with my meager C++ skills to solve a mystery but after 3 days at this, I am stumped. I built a C++ DLL to wrap an existing VB dll (that had it's own challenges) but I don't THINK that is the problem. The C++ DLL simply calls one function from the VB DLL which returns a value. I want to return THAT value (a Variant) to my program. After building and compiling it, it tested it by calling it from a quick and dirty VB app and it worked fine. However, when I call it from actual app that uses it, I get a access violation (0xcccccccc) but only in certain circumstances. Here is the code:
extern "C" BSTR PASCAL EXPORT BldSubs(VARIANT lAbsID,VARIANT lLine,VARIANT bHTML)
int msgid = 0;
char szResult = "G";
char szGood = "G";
char szBad = "B";
r0 = p.bldsublist(&lAbsID,&lLine,&bHTML);
msgid = MessageBox(NULL,szResult,"Test DLL 1",MB_OKCANCEL);
msgid = MessageBox(NULL,szResult,"Test DLL 2",MB_OKCANCEL);
it is the strcpy function that is causing it to croak. If I change the strcpy statement to strcpy(szResult,szBad); then the code will properly run and I will get both a message box with "G" and then "B". However, the strcpy of the variant seems to blow things up.
The program doing the calling is a Basicscript app which has successfully called functions from another C++ DLL. I'll get an access violation is I use the strcmp, strcpy or strcat. Anything that attempts to access the returned variant give me an access violation.
So, what have I been missing here? Something isn't happening when I run this in basicscript, something is not initialized, but what is it? Again, this DLL runs fine when called from a VB app.
What if you use strncpy instead of strcpy when copying r0.pcVal, something like this:
strncpy(szResult, ro.pcVal, 1);
szResult='\0'; // To be really safe!
My guess is that the strcpy is copying more characters than szResult can hold.
I thought about that, but didn't implement it thinking that if the buffer was being overrun, it would die in a call from VB just like it would in the basicscript call.
But I tried it anyway and I still get the error.
I suspect (and I am not the least bit knowledgeable on this) that it a stack or alignment problem. Maybe Basicscript can't access the stack in certain regions or something like that...
Just a stupid thought:
In C/C++, a string is stored as an array of characters with the string in elements 0 through (len-1) and with a NUL ('\0') in array element len. The length is given implicitly by the placement of that NUL.
How does VB handle strings? In the other forms of BASIC I've worked with, a string was stored in an array of characters in elements 1 through len and with the string length stored explicitly in element 0. There is no NUL in that character array. And that the string length is stored in a byte is the reason why string lengths were limited to 255.
So, does VB handle strings in the traditional way or in the C/C++ way? Therein may lie the incompatibility that allowed the DLL to work when called in VB yet crash in C++.
Actually, that is a pretty good thought and I have spent some time trying to understand the Variant data type and specifically how they relate to strings. I was wondering if the return value type was somehow part of the problem here, so I changed the return type to be a BOOL in my C++ DLL and changed both my Test VB program and then the BasicScript app to look for a boolean return type. The VB app works, the BasicScript app gives me the same Access Violation error. I think the 0xcccccccc address is telling me that the variable isn't initialized perhaps it has gone out of scope although I pass the values byVal, perhaps the return value is coming back byRef and the called DLL has already released the memory...but my local variable should be holding the value...unless the value returned IS the memory address and is no longer valid...hmmmm.
Like I said, C++ is not my strong suit..I'll do a little more research on the "return value" side of this equation. Its obvious that VB and BasicScript handle these values differently, I just wonder what that difference is...or perhaps it has nothing to do with the return value and is just a problem with my DLL (MFC vs Win32?).
Thanks.. and keep those ideas coming.