A question about the code exception - c++

Env: VS 2008, C++
I have code like below:
void HopeException(LPVOID nVerify)
{
char *p = NULL;
p = (char *)nVerify;
delete []p;
}
When I invoke the function "HopeException" with parameter not-NULL, like:
HopeException(123);
then I hope the program will throw an exception.
But when I compile the code on VS 2008 with Release mode, the program runs well.
I don't know why. Could anyone give me a help about this issue?
Or do you have any good idea to implement the feature with another method?
Edit:
I am so sorry, I think I posted the wrong code before.
Actually, I am doing protection for my software.
My software will get the CRC value of DLL file, and then my software will check the CRC value like below:
unsigned int VerifyCRC = FF234322;
unsinged int CRC = getCRC("Fun.dll");
LPVOID lpResult = CRC & (~VerifyCRC);
HopeException(lpResult);
So according the code below, if the cracker cracks the Fun.dll file, the execute will throw out an exception.
That is really I want.

Jell - C++ gives you enough rope to hang yourself (and most probably most of you friends).
But why do it? (- Suppose it depends on your friends).

You're treating nVerify as an address and assigning it to your pointer p, and then invoking delete[] on that address. If the value of nVerify isn't a valid address you can get undefined behavior, which includes the program appearing to "run well" mostly because you're not really doing much in this function.
What are you really trying to do?

That code shouldn't compile in C++; the closest thing that should compile fine is:
void HopeException(int nVerify)
{
char *p = NULL;
p = (char *)nVerify;
delete []p;
}
This code will crash on VS 2010 Express, so I assume it will also crash in VS 2008. If your goal is to throw a debugger exception directly (on x86) you can just use
__asm int 3;
If your goal is to break into the debugger you can also just use
DebugBreak();

Related

Using 'new' to allocate memory dynamically in C++?

I am working on some C++ code and am having some problems with the function described below. I haven't used much C++ before, at least not for a long time and so i'm trying to learn as I go along to a large extent. The win32api doesn't help much with the confusion factor either...
The function is succesfully called twice, before failing when called at a later stage when it is called in the application.
PTSTR getDomainFromDN(PTSTR dnPtstr) {
size_t nDn=wcslen(dnPtstr);
size_t *pnNumCharConverted = new size_t;
wchar_t *szTemp = new wchar_t[10]; // for debugging purposes
_itow_s((int)nDn,szTemp,10,10); // for debugging purposes
AddToMessageLog(EVENTLOG_ERROR_TYPE,szTemp); // for debugging purposes (displays an integer value before failing)
AddToMessageLog(EVENTLOG_ERROR_TYPE,TEXT("Marker A")); // for debugging purposes
char *dn = new char[nDn];
// !!!!!!!!!!!! all goes wrong here, doesn't get to next line, nDn does have a value when it fails (61)
AddToMessageLog(EVENTLOG_ERROR_TYPE,TEXT("Marker B")); // for debugging purposes
wcstombs_s(pnNumCharConverted,dn,nDn+1,dnPtstr,nDn+1);
...more code here...
delete[] dn;
delete pnNumCharConverted;
return result
}
At first i thought it was a memory allocation problem or something as it fails on the line char *dn = new char[nDn];, the last marker showing as 'Marker A'. I used delete[] on the pointer further down to no avail. I know that nDn is a value because I print this out to a message log using _itow_s for debugging. I also know that dnPtrstr is a PTSTR.
I tried using malloc as well with free() in the old C style but this doesn't improve things.
I tried sanitizing your code a bit. One of the big tricks to C++ is to not explicitly use memory management when it can be avoided. Use vectors instead of raw arrays. Strings instead of char pointers.
And don't unnecessarily allocate objects dynamically. Put them on the stack, where they're automatically freed.
And, as in every other language, initialize your variables.
PTSTR getDomainFromDN(PTSTR dnPtstr) {
std::wstring someUnknownString = dnPtstr;
size_t numCharConverted = 0;
std::wstring temp; // for debugging purposes
std::ostringstream sstr;
sstr << temp;
AddToMessageLog(EVENTLOG_ERROR_TYPE,sstr.str().c_str()); // for debugging purposes (displays an integer value before failing)
AddToMessageLog(EVENTLOG_ERROR_TYPE,TEXT("Marker A")); // for debugging purposes
std::vector<char> dn(someUnknownString.size());
AddToMessageLog(EVENTLOG_ERROR_TYPE,TEXT("Marker B")); // for debugging purposes
wcstombs_s(&numCharConverted, &dn[0], dn.size(), someUnknownString.c_str(), dn.size());
...more code here...
return result
}
This might not have solved your problem, but it has eliminated a large number of potential errors.
Given that I can't reproduce your problem from the code you've supplied, this is really the best I can do.
Now, if you could come up with sane names instead of dnPtstr and dn, it might actually be nearly readable. ;)
i think your problem is this line:
wcstombs_s(pnNumCharConverted,dn,nDn+1,dnPtstr,nDn+1);
because you are telling wcstombs_s to copy up to nDn+1 characters into dn which is only nDn characters long.
try changing the line to:
wcstombs_s(pnNumCharConverted,dn,nDn,dnPtstr,nDn);
or perhaps better yet:
wcstombs_s(pnNumCharConverted,dn,nDn,dnPtstr,_TRUNCATE);
im not sure how you are debugging this or how AddToMessageLog is implemented, but if you are just inspecting the log to trace the code, and AddToMessageLog is buffering your logging, then perhaps the error occurs before that buffer is flushed.
If you are sure that "char *dn = new char[nDn];" is failing, TRY "set_new_handler" -> http://msdn.microsoft.com/en-us/library/5fath9te(VS.80).aspx
On a side note, few things:
The very first operation "size_t nDn=wcslen(dnPtstr);" is not 100% correct. You are doing wcslen on dnPtstr assuming dnPtstr to be unicode. However, this is not the case since it could be PWSTR or PSTR based on whether UNICODE is defined or not. So, use _tcslen(). Its better if you give some time to understand UNICODE, NON-UNICODE stuff since they would help you a lot in Windows C++ development.
Why are you using so many "new" if you are using these variables only in this function (I am assuming it). Prefer stack over heap for local variables unles you have a definite requirement.

dynamic cast throws pointer is not std::__non_rtti_object

I'm having problem with dynamic_cast. i just compiled my project and tested every thing in debug mode and then i tried compiling it in release mode, i have copied every configuration from debug mode exept optimization parameter which is now /o2, (while debuging i set it as /od) the project compiled but when it starts loading my resources i got exception in the piece of code here :
for(int j = 1; j < i->second->getParametersNumber();j++)
{
CCTMXTiledMap* temp = CCTMXTiledMap::tiledMapWithTMXFile(i->second->As<string>(j).c_str());
CCTMXLayer* ret = NULL;
for(NSMutableArray<CCNode*>::NSMutableArrayIterator l=temp->getChildren()->begin();!ret && l!=temp->getChildren()->end();l++)
ret = dynamic_cast<CCTMXLayer*> (*l);
t1.first = ret;
templates[i->first].second.push_back(t1);
templates[i->first].second.back().first->retain();
}
nothing in code changed and when I check in debugger every variable in classes is what it should be but dynamic cast is throwing std::__non_rtti_object. what am i doing it wrong? and i'm using cocos2d-x ,I didn't have enough reputation to add that tag!
Does CCNode have any virtual functions? Are all elements of temp->getChildren()->begin() really CCNodes? Does temp->getChildren() return a reference? The latter is especially insidious: you call both temp->getChildren()->begin() and temp->getChildren()->end(). If getChildren() returns a copy, you're taking the begin of one copy and the end of another copy.
In this case after many code changes I found out there has to be some bugs which show themselves when code is optimized (still don't know if it's compiler's mis optimization or my code has some problems but it's probably mine). and the main reason for that problem was with *l being NULL.

invalid cruntime parameter _itoa_s

I have experienced a strange behavior when using _itoa_s and _ultoa_s if I try to get a char array from an DWORD. The function returns zero(success) and my application continues, but I'm getting an exception window with error code 0xc0000417 (STATUS_INVALID_CRUNTIME_PARAMETER).
ULONG pid = ProcessHandleToId(hProcess);
int size = getIntSize(pid);
char *pidStr = new char[size+1];
_ultoa_s(pid, pidStr, size+1, 10);
//do sth with pidStr...
delete[] (pidStr);`
ProcessHandleToId returns the PID (DWORD) for a given ProcessHandle.
getIntSize returns the number of numbers to the corresponding int/char array (5555 => 4).
Yes, the safe CRT functions will abort your program with status code 0xc0000417 when they detect a problem. However, they will do this immediately, the function will not return.
Which means that you are looking at the wrong source code for this problem. It isn't the _ultoa_s() call that's bombing your program. It's another function call, somewhere else in your code. I can't help you find it of course. But the debugger should give you a good idea, look at the call stack when it breaks.
I just compiled your code and it runs fine. The int to string conversion is correct. I assume you bump into security issues due to missing permission when trying to access process handles you don't own.

w8004 compiler warning BDS6 c/c++

It is a best practise to initialise a variable at the time of declaration.
int TMyClass::GetValue()
{
int vStatus = OK;
// A function returns a value
vStatus = DoSomeThingAndReturnErrorCode();
if(!vStatus)
//Do something
else
return(vStatus);
}
In the debug mode, a statement like this int vStatus = OK; is causing no issues during DEBUG MODE build.
The same when build in RELEASE MODE, throws a warning saying:
w8004: 'vStatus' is assigned a value that is never used.
Also, i am using the same variable further down my code with in the same function,like this if(!vStatus)and also I return the value of return(vStatus);
When I looked at the web for pointers on this debug Vs Release, compilers expect you to initialise your variable at the time of declaring it.
I am using Borland developer studio 6 with windows 2003 server.
Any pointers will help me to understand this issue.
Thanks
Raj
You initialise vStatus to OK, then you immediately assign a new value.
Instead of doing that you should initalise vStatus with a value that you're going to use.
Try doing the following instead:
int TMyClass::GetValue()
{
// A function returns a value
int vStatus = DoSomeThingAndReturnErrorCode();
if(!vStatus)
//Do something
else
return(vStatus);
}
Edit: Some clarification.
Initialising a variable, only to never use that value, and then to assign another value to the variable is inefficient. In your case, where you're just using int's it's not really a problem. However, if there's a large overhead in creating / copying / assignment for your types then the overhead can be a performance drain, especially if you do it a lot.
Basically, the compiler is trying to help you out and point out areas in your program where improvements can be made to your code
If you're wondering why there's no warning in debug mode, it's because the passes that perform dataflow analysis (which is what finds the problem) are only run as part of optimization.

calling code stored in the heap from vc++

Imagine I am doing something like this:
void *p = malloc (1000);
*((char*)p) = some_opcode;
*((char*)p+1) = another_opcode; // for the sake of the example: the opcodes are ok
....
etc...
How can I define a function pointer to call p as if it was a function? (i'm using VC++ 2008 express).
Thanks
A comment wasn't enough space. Joe_Muc is correct. You should not stuff code into memory obtained by malloc or new. You will run into problems if you change the page properties of pages that Windows allocates.
This isn't a problem becuase using VirtualAlloc() and the related WIn32 APIs is every easy: call VirtualAlloc() and set the flProtect to [PAGE_EXECUTE_READWRITE][2]
Note, you should probably do three allocations, one guard page, the pages you need for your code, then another guard page. This will give you a little protection from bad code.
Also wrap calls to your generated code with structured exception handling.
Next, the Windows X86 ABI (calling conventions) are not well documented (I know, I've looked). There is some info here, here, here The best way to see how things work is to look at code generated by the compiler. This is easy to do with the \FA switches ( there are four of them).
You can find the 64-bit calling conventions here.
Also, you can still obtain Microsoft's Macro Assembler MASM here. I recommend writing your machine code in MASM and look at its output, then have your machine code generator do similar things.
Intel's and AMD's processor manuals are good references - get them if you don't have them.
Actually, malloc probably won't cut it. On Windows you probably need to call something like [VirtualAlloc](http://msdn.microsoft.com/en-us/library/aa366887(VS.85).aspx) in order to get an executable page of memory.
Starting small:
void main(void)
{
char* p = (char*)VirtualAlloc(NULL, 4096, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
p[0] = (char)0xC3; // ret
typedef void (*functype)();
functype func = (functype)p;
(*func)();
}
The next step for playing nice with your code is to preserve the EBP register. This is left as an exercise. :-)
After writing this, I ran it with malloc and it also worked. That may be because I'm running an admin account on Windows 2000 Server. Other versions of Windows may actually need the VirtualAlloc call. Who knows.
If you have the right opcodes in place, calling can be as simple as casting to a function pointer and calling it.
typedef void (*voidFunc)();
char *p = malloc (1000);
p[0] = some_opcode;
p[1] = another_opcode; // for the sake of the example: the opcodes are ok
p[n] = // return opcode...
((voidFunc)p)();
Note though that unless you mark the page as executable, your processor may not let you execute code generated on the heap.
I'm also currently looking into executing generated code, and while the answers here didn't give me precisely what I needed, you guys sent me on the right track.
If you need to mark a page as executable on POSIX systems (Linux, BSD etc.), check out the mmap(2) function.