I was reading Moai source code, and I became curious about why this should cause a crash (or not...)
I do not really understood that snippet.
In file A:
#define UNUSED(p) (( void )p)
In file B:
//----------------------------------------------------------------//
/** #name crash
#text Crashes Moai with a null pointer dereference.
#out nil
*/
int MOAISim::_crash ( lua_State* L ) {
UNUSED(L);
int *p = NULL;
(*p) = 0;
return 0;
}
EDIT:
I think part of what I was not understanding is what "deference" means. So if you put that in your answers it would be awesome.
The crash is caused by the dereference of the null pointer:
(*p) = 0; // <--- Crash
Also as pointed out in the comments, the UNUSED macros is only there to suppress the "unused parameter" warning that most compilers will give.
It is usually also possible to prevent the warning by, simply, not specifying the variable name as follows:
int MOAISim::_crash ( lua_State* )
{
int *p = NULL;
(*p) = 0;
return 0;
}
It's also worth bearing in mind that the above is not a guaranteed crash. On one of the 32-bit consoles de-referencing a null pointer actually resulted in the number "3". This did make null dereferences quite hard to find, but generally if you saw a 3 sitting around in a register you could hazard a good guess as to what had just gone wrong.
Dereferencing is essentially asking for the value stored at a given pointer. If the pointer is not valid (that is, pointing at a memory location that the process does not own) then it results in a crash. In Windows this is called an Access Violation (0xC0000005). Under Linux it's a Segmentation Violation, SIGSEGV.
See also
The macro is replaced in the code, so for the compiler the function looks like this:
int MOAISim::_crash ( lua_State* L ) {
(( void )L);
int *p = NULL;
(*p) = 0;
return 0;
}
The (( void )L) line evaluates L and throw away the result. The crash, however, isn't from that line, instead it from the assignment to a NULL address at (*p) = 0.
int *p = NULL;
(*p) = 0;
The second line is an undefined behaviour (dereferencing a nullptr pointer). The fact that is crashes the application on your platform is just one form of undefined behavior (in my opinion good, because you can catch bugs sooner).
Related
I am a c++ learner. Others told me "uninitiatied pointer may point to anywhere". How to prove that by code.?I made a little test code but my uninitiatied pointer always point to 0. In which case it does not point to 0? Thanks
#include <iostream>
using namespace std;
int main() {
int* p;
printf("%d\n", p);
char* p1;
printf("%d\n", p1);
return 0;
}
Any uninitialized variable by definition has an indeterminate value until a value is supplied, and even accessing it is undefined. Because this is the grey-area of undefined behaviour, there's no way you can guarantee that an uninitialized pointer will be anything other than 0.
Anything you write to demonstrate this would be dictated by the compiler and system you are running on.
If you really want to, you can try writing a function that fills up a local array with garbage values, and create another function that defines an uninitialized pointer and prints it. Run the second function after the first in your main() and you might see it.
Edit: For you curiosity, I exhibited the behavior with VS2015 on my system with this code:
void f1()
{
// junk
char arr[24];
for (char& c : arr) c = 1;
}
void f2()
{
// uninitialized
int* ptr[4];
std::cout << (std::uintptr_t)ptr[1] << std::endl;
}
int main()
{
f1();
f2();
return 0;
}
Which prints 16843009 (0x01010101). But again, this is all undefined behaviour.
Well, I think it is not worth to prove this question, because a good coding style should be used and this say's: Initialise all variables! One example: If you "free" a pointer, just give them a value like in this example:
char *p=NULL; // yes, this is not needed but do it! later you may change your program an add code beneath this line...
p=(char *)malloc(512);
...
free(p);
p=NULL;
That is a safe and good style. Also if you use free(p) again by accident, it will not crash your program ! In this example - if you don't set NULL to p after doing a free(), your can use the pointer by mistake again and your program would try to address already freed memory - this will crash your program or (more bad) may end in strange results.
So don't waste time on you question about a case where pointers do not point to NULL. Just set values to your variables (pointers) ! :-)
It depends on the compiler. Your code executed on an old MSVC2008 displays in release mode (plain random):
1955116784
1955116784
and in debug mode (after croaking for using unitialized pointer usage):
-858993460
-858993460
because that implementation sets uninitialized pointers to 0xcccccccc in debug mode to detect their usage.
The standard says that using an uninitialized pointer leads to undefined behaviour. That means that from the standard anything can happen. But a particular implementation is free to do whatever it wants:
yours happen to set the pointers to 0 (but you should not rely on it unless it is documented in the implementation documentation)
MSVC in debug mode sets the pointer to 0xcccccccc in debug mode but AFAIK does not document it (*), so we still cannot rely on it
(*) at least I could not find any reference...
I was working with pointers and was trying different things.
So here I made a general print function
void print(const int &value)
{
cout << "value = " << value << " & address = " << &value << endl;
}
Now Here's a code that works somehow:
int j = 9090;
int* p;
*p = j; //Please read further
print(*p);
I know *p = j is something illogical and I should have done p = &j or p = new int etc.... but why did this work?
The output was
value = 9090 & address = 0x28ff48
Moreover if I print j, the address is 0x28ff44. Which means it allocated new memory automatically for p (as its address is ..48)
Now, if I only add another line before j's declaration:
int i = 80;
int j = 9090;
int* p;
*p = j; //Please read further
print(*p);
^The program crashes.
However if I add this i's line after declaration of p the program runs.
int j = 9090;
int* p;
int i = 80;
*p = j;
print(*p);
Am I doing something wrong? I was using GCC compiler in Dev C++ IDE 4.9.9.2. What's going on?
The problem is that dereferencing an uninitialised pointer is undefined.
This means that anything can happen - sometimes a program will crash, sometimes just give strange results, and sometimes (if you're unlucky) it will just seem to work.
Since your pointer is uninitialised, you will access memory at whatever random location it happens to represent.
Sometimes, this is a valid address, and the program will keep running.
Sometimes, it's an invalid address, and the program will crash.
int* p;
*p = j;
This is correct syntax of C++. It means that in field which address is in p, you put value of j. The problem with crash originate from the fact that you don't provide any memory for p. When you say int * p it means that you have pointer on int variable. However you didn't provide any real address in memory to store int value. There is some rubbish in p but this rubbish is considered to be valid address by program and it tries to write value of j there. If you are lucky and this address was not used the program will work further. Otherwise it will crash. To avoid such undefined behaviour you need to allocate memory for p:
int* p = new int;
*p = j;
I know *p = j is something illogical
In this case it is undefined behavior. You are dereferencing a pointer that wasn't initialized, so it effectively points to an unknown (random) location.
Which means it allocated new memory automatically for p
No, it didn't. The address you see is just the random, undefined value which ended up in your uninitialized pointer.
why did this work?
That's the thing with undefined behavior: It might work by coincidence, for example if the random value in the pointer happened to point into some valid, writable memory region, your code would work fine for that specific run. Another time, it might just crash. Yet another time, it might corrupt your heap, or some unrelated data, and cause a seemingly unrelated crash or bug some time later. Which is just screaming for long nights in front of your debugger ;)
Bottom line: Don't do it - avoid UB at all cost.
However if I add this i's line after declaration of p the program runs.
I think the behavior you observe (crash vs. no crash) is not directly related to the code changes, but coincidental. In fact, if you'd run the "working" version multiple times, I'm sure you'd still get a crash after some time.
I have following two versions of code
correctly working program
#include<iostream.h>
#include<string.h>
void main()
{
const char *q="+\0";
char *p=""; //working correct with ""
strncpy(p,q,2);
cout<<p;
}
Program giving error
#include<iostream.h>
#include<string.h>
void main()
{
const char *q="+\0";
char *p=NULL; //Program gives error abnormal termination when *p=NULL or *p="\0"
strncpy(p,q,2);
cout<<p;
}
I am not understanding the two different behavior of the char *p in these code samples.
Please help.
No part of your program is correct. The memory that contains string literals must not be modified, so you must never copy to the location p.
You must only access memory that you personally obtained for your own use, like so:
char p[500];
strncpy(p, "+\0", 2); // OK, *p is yours
I believe you actually mean when p == NULL (from your comment)
*p == NULL just means p points to some address which holds the value 0.
In other words *p == NULL and p == NULL are two completely different things.
So if you tried to edit the memory where p points to, and that memory is address 0x0000 (also known as NULL) that is pretty much guaranteed to fail, because you likely do not own this memory.
When I say own, I mean your program has allocated memory at this location. If you write char *p = new char; then your program allocates some sizeof(char) bytes of memory. And now if you modify the value of *p that is okay because you have been given the memory (by the operating system or whatever).
I use some function, and this function return variable of LPWSTR type (wchar_t*)
at debugger i look at this variable and see error "0x2e (Address 0x2e out of bounds)"
and when i do some operations with its variable, my program terminated.
I can't change called function, i haven't its src code.
my question is : Is c/c++ language have functions to check situation before call incorrect variable? i try try/catch block, but its not helped.
Excuse me for my english and thanks for any help
edited:
fragment of code with error
PCERT_EXTENSION pCe = CertFindExtension(szOID_CRL_DIST_POINTS, pCertInfo->cExtension, pCertInfo->rgExtension);
if (pCe) {
PCRL_DIST_POINTS_INFO pCrlDistPointsInfo = NULL;
PCRL_DIST_POINT *pCrlDistPointsPtr = NULL;
PCRL_DIST_POINT pCrlDistPoints = NULL;
DWORD pdwCrlDistPoints = sizeof (CRL_DIST_POINTS_INFO);
if (!CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
szOID_CRL_DIST_POINTS,
pCe->Value.pbData,
pCe->Value.cbData,
CRYPT_DECODE_ALLOC_FLAG,
(PCRYPT_DECODE_PARA) NULL,
&pCrlDistPointsInfo,
&pdwCrlDistPoints)) {
printf("\n\nCannot decode CRL URL.\n\n");
}
if (pCrlDistPointsInfo) {
pCrlDistPointsPtr = (PCRL_DIST_POINT*) pCrlDistPointsInfo->rgDistPoint;
if (pCrlDistPointsPtr && pCrlDistPointsInfo->cDistPoint > 0) {
findCDP = true;
fwprintf(pFile, L"^^");
for (int i = 0; i < pCrlDistPointsInfo->cDistPoint; i++) {
pCrlDistPoints = &pCrlDistPointsInfo->rgDistPoint[i];
if (pCrlDistPoints) {
LPWSTR str = (LPWSTR) pCrlDistPoints->DistPointName._empty_union_.FullName.rgAltEntry->_empty_union_.pwszURL;
//printf("last error= 0x%08X", GetLastError());
fwprintf(pFile, str);//PROGRAM TERMINATED HERE!!!
fwprintf(pFile, L";");
}
printf("%d\n",i);
}
}
free(pCrlDistPointsInfo);
}
}
No, it doesn't have. If you set a pointer, which points to an invalid memory location, every access to the object at that location is an undefined behavior. What will most likely happen is a crash or some kind of memory corruption.
If a pointer has value 0x0000002e, it can mean only two things:
A bug in code which returns that. You're out of luck if you can't fix that...
An undefined pointer value, and reason for error is returned some other way, such as by modified reference parameter. But returning undefined value instead of null pointer would still count as a bug in my book.
On the other hand 0x2e sounds like ASCII character, '.' to be exact, so are you sure you are looking at pointer value instead of the string pointed to?
Late edit: looking at the code, it seems unions are involved. A possible reason for crash then is, you are accessing wrong member of union. In C union, all members/fields are in same memory location, they overlap. In other words, union can hold only one value at a time, and you need to know which one somehow, such as from documentation of function which initializes the union value, or by some extra variable which tells the type (common pattern in C is to have struct which contains type field and union field).
Windows has functions to check whether an address is a correct address or not. BUT... it's bad practice to rely on this, since there is no guarantee that if the pointer points to a correct address, that this is the address that you want.
The functions in windows are: IsBadReadPtr, IsBadWritePtr and IsBadCodePtr. I strongly suggest to only use these functions in debugging code (asserts e.g.) and never rely on this in a release executable.
If your application is designed and working correctly, you should never rely on these Windows functions.
I have a zap() function written to deallocate a 1-d array as follows.
void zap(double *(&data))
{
if (data != NULL)
{
delete [] data;
data = NULL;
}
return;
}
I was under the impression that if data != NULL would not try to deallocate memory that had never been allocated, but I think I am mistaken. I am having the following implementation problem.
void fun()
{
int condition = 0;
double *xvec;
double *yvec;
allocate_memory_using_new(yvec); //a function that allocates memory
if (condition == 1) allocate_memory_using_new(xvec);
//some code
//deallocate memory:
zap (yvec);
zap (xvec); //doesn't work
return;
}
The output is the following:
Unhandled exception at 0x6b9e57aa (msvcr100d.dll) in IRASC.exe: 0xC0000005: Access
violation reading location 0xccccccc0.
So I realize it is not a desirable thing to try to call zap when it is obvious that the pointer was never actually used. I am just wondering if there is a way to check the address of the pointer at some point in the zap() function to avoid the exception. Thanks in advance for your help and insight!
Pointers do not get magically initialized to 0, only when they are global or static. You need to do so:
double *xvec = NULL;
double *yvec = NULL;
If you do not, they contain random junk that was left on the stack where they are created. And this junk is most of the time not NULL.
Also, you do not need to check against NULL, as delete is a no-op in that case:
double* xvec = NULL;
delete xvec; // perfectly valid
Further, if you're working with Visual Studio 2010, I recommend to use nullptr instead of NULL.
The values of xvec and yvec point to random numbers, not NULL. I think your allocate_memory function isn't working properly, as it usually would return a pointer to a block of memory, which you would assign to xvec and yvec
In C++ pointers are not initialized automagically to NULL as in other languages (think Java), so the value of xvec (pointer) is undefined, and might or not be NULL when you test.
void fun()
{
double *xvec; // value of xvec undefined, might be 0 or not
// ...
zap (xvec); // if it is not 0, you will try to delete: Undefined Behavior
}
The simple solution is initializing the pointer in the definition double *xvec = 0;. Also, you do not need to test for NULL (or 0) in your zap function, delete will not cause undefined behavior if called on a null pointer:
template <typename T>
inline void zap( T *& p ) {
delete p;
p = 0;
}
I've concluded the the array forms of new and delete qualify as C++ anti-patterns -- they seem reasonable, but in reality almost any and all use of them is basically guaranteed to lead to more grief and problems than usable code.
As such, I'd say that trying to fix your zap is a bit like finding finding a woman who's just been in a fire and gotten 3rd degree burns on at least 85% of her body, and trying to make her better by trimming the fingernail she broke while escaping from the fire.