2

Example.

If I have a pointer,

int* p;
p = (int*)2; // just for test
*p = 3; // it will be crack, right?

In general, the access of the pointer of value 2 will be crack. But actually the crack is not so simple. Invalid value of the pointer maybe comes from the Runtime error. I'd like to find a way to check the pointer before accessing it.

SDJSK
  • 1,292
  • 17
  • 24

3 Answers3

6

In standard C99, this (dereferencing (int*)2 in your *p =3; statement) is undefined behavior (UB). Read C.Lattner's blog on that. You should be very scared of UB. This is why programming in C is so hard (other programming languages like Ocaml, Common Lisp have much less UB).

A C program may have undefined behavior but might not always crash.

In practice, when coding in C, be vary careful about pointers. Initialize all of them explicitly (often to NULL). Be very careful about pointer arithmetic. Avoid buffer overflows and memory leaks. Static source code analysis may help (e.g. with Frama-C) but is limited (read about halting problem & Rice's theorem). You could use quite often flexible array members and check pointers and indexes at runtime.

On some embedded freestanding C implementations (e.g. coding for Arduino like devices), some addresses might have particular meanings (e.g. be some physical IO devices), hence UB could be very scary.

(I am focusing on Linux below)

On some implementations, and some operating systems, you might test if an address is valid. For example on Linux you might parse /proc/self/maps to compute if some given address is valid (see proc(5) for more about /proc/).

(therefore, you could write -on Linux- some function bool isreadableaddress(void*) which would parse /proc/self/maps and tell if an address is readable in the virtual address space of your process; but it won't be very efficient since needing several system calls)

And you should use valgrind and compile with all warnings & debug options (gcc -Wall -Wextra -g) and use the debugger (gdb) and some more debugging compiler options like -fsanitize=address

You might perhaps handle the SIGSEGV signal, but it is very tricky and highly non-portable (operating system, processor, and ABI specific). Unless you are a guru, you should not even try.

Community
  • 1
  • 1
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • The OP seems to be asking about whether the pointer can be checked, though. – Flying_Banana Dec 12 '15 at 15:45
  • 3
    Beware that on Windows there are functions that appear to do exactly what the OP wants (IsBadReadPtr etc). Do not use them: https://blogs.msdn.microsoft.com/oldnewthing/20060927-07/?p=29563/ (Title is "IsBadXXXPtr should really be called CrashProgramRandomly") .There *may* be somebody who knows more about Windows than the author of that article, but I wouldn't want to bet on it. Every windows programmer should read the blog. – Martin Bonner supports Monica Dec 12 '15 at 15:50
3

Yes, "it will be crack".

Your program has no way to know whether an arbitrarily-initialised pointer will practically "work" at runtime. Firstly, you compile your code before you run it, potentially on a completely different computer. The compiler cannot predict the future.

The language deals with this by saying any pointer not explicitly made to point to an object or array that you created in the program cannot exist as long as you want your program to have well-defined behaviour.

Basically, the only way to be sure is to not do this.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
0

Actually it is possible... sort of....

Not with plain C, but most environments allow you to test whether a you can write to a pointer...

for example

Unfortunately you have no way of knowing if a pointer points at what you intend. Meaning you can be pointing at another valid address, different from what you expect, and unintentionally corrupt a piece of your own memory...

char a[2];
int b; // assuming they are stored on the stack sequentially and aligned one right after the other...

char *ptr = (char*)a;

ptr += 3;

*ptr = 'b' // valid pointer, but probably an error....
AK_
  • 7,981
  • 7
  • 46
  • 78
  • How does that answer the question of dereferencing `(int*)2` ? Also, Martin Bonner commented (my answer) and cite https://blogs.msdn.microsoft.com/oldnewthing/20060927-07/?p=29563/ which basically discourage using `IsBadWritePtr` on Windows... – Basile Starynkevitch Dec 12 '15 at 17:16
  • have you read the title of his post? he doesn't care about `(int*)2` ... it's just an example... I tried to explain, in simple terms, why what he is asking for is essentially impossible. – AK_ Dec 12 '15 at 17:29
  • 2
    On Linux, it is possible (thru `/proc/self/maps`) to tell if a given address is readable. But your argument applies. A valid address might not point to something intended. – Basile Starynkevitch Dec 12 '15 at 17:39
  • Cool :-) . some more characters – AK_ Dec 12 '15 at 17:42
  • `*ptr = 'b'` is not a *valid pointer*. It may crash or not crash. for example `a` could be just before the return address on the stack, of if you execute under valgrind, it may stop the program. – chqrlie Dec 12 '15 at 22:30
  • Please read the answer again... For the sake of the example, I assume that, at that line 'ptr' will point to an address where 'b' is – AK_ Dec 12 '15 at 22:39