2

In my function, a memory pointer and its size are passed as parameters:

int myFun(uintptr_t* mem_ptr, int mem_size) {
    // Code here
}

Is there any way to tell if this chunk of memory is really valid?

(The Operating System is CentOS Linux release 7.9.2009.)

digito_evo
  • 3,216
  • 2
  • 14
  • 42
  • 1
    What exactly do you mean by "tell if is really valid"? If the pointer points to valid memory? – UnholySheep May 13 '22 at 07:34
  • 1
    Simply access it. If you get a segfault is a good hint that the pointer was totally wrong... Sorry, but, if using C++, you should start thinking about the fundamental concepts of programming. Passing raw pointers and sizes is a bit near to assembler... sometimes useful, but if you fear of invalid pointers... something is wrong here! and the answer to your question: No, you can't! Even if you pass chechsums in the content, you get never any guarantee if the rest of the prog is able to pass invalid pointers – Klaus May 13 '22 at 07:35
  • If it is about valid *content* of the buffer – have you thought of a check sum? – Aconcagua May 13 '22 at 07:38
  • Which operating system are you targeting? – Bathsheba May 13 '22 at 07:44
  • @Klaus yes, the program want to check if the pointer points to valid memory. If this doesn't work, is there any alternative to pass the memory? thanks for your suggestion. – 北冥有鱼 May 13 '22 at 08:09
  • You cannot do this portably which is why I'm asking you about the OS. – Bathsheba May 13 '22 at 08:10
  • @Bathsheba My operating system is CentOS Linux release 7.9.2009 . – 北冥有鱼 May 13 '22 at 08:11
  • Start by looking at `msync`. (One of the errors you get back will tell you if you own the memory or not.) Note that in Windows, you have `IsBadReadPtr` and friends. Of course this is not completely foolproof - the memory may have been `free`d, but not yet given back to the OS. – Bathsheba May 13 '22 at 08:12
  • It's the caller's responsibility to ensure that the arguments being passed to the callee are all valid (depending on what exactly valid means in a particular case). – digito_evo May 13 '22 at 08:16
  • Trivial edit so I can convert my downvote to an upvote. (Now the OS has been clarified.) I don't see why there could be a fault in the question - the OP might be writing a debugger for example. – Bathsheba May 13 '22 at 08:19
  • Maybe this helps: https://stackoverflow.com/a/30197585/17862371 – Jakob Stark May 13 '22 at 08:45

2 Answers2

6

Don't. Just don't.

Even if you could find a way to check whether the pointer can safely be dereferenced, that doesn't mean it points where you think it does! It might point into your call stack, into your read-only code segment, into the static variables of some library that you're using, or any other place in memory that your program happens to have access to.

The responsibility of passing a valid pointer should be with the caller of the function. To make it harder for the caller to do something stupid, consider passing a std::vector & or std::vector const & instead.

Thomas
  • 174,939
  • 50
  • 355
  • 478
1

It's simple. Don't write such code.

It's prone to errors just like you want to check for. That's why modern c++ has invented for example std::span. A span represents a contiguous sequence of objects just like your pointer + size. But the pointer and size are not separate values that you can easily mix up in function calls. It's a single object containing both.

Actually if the size is known at compile time it gets encoded in the type itself and the span only contains a pointer making it smaller and allowing for better optimization of the function.

Beyond that you have to trust the users of your function don't lie to you. There is no good way to validate a pointer, a problem that hunts garbage collectors, and it's best to just let the OS tell you when the pointer is total garbage by producing a segfault.

Note: Using span instead of array makes is even simpler than passing pointer + size:

#include <span>

int get(std::span<int> x, size_t i) {
    return x[i];
}

int main() {
    int x[] = {2, 3, 5, 7, 11};
    return get(x, 2);
}

A std::span can be constructed from an array of known size so the compiler does all the work for you.

Goswin von Brederlow
  • 11,875
  • 2
  • 24
  • 42