4

I am trying to debug a crash issue where memcpy is trying to access a memory location which does not exist and fails. Following is a reduced version of the problem code:

void func_foo(int **a) {
   int *b, c;
   if (*a) {
       b = *a;
   }
   memcpy(&c, b, sizeof(int));//this crashes because address "b" is not accessible.
}

My question is: is there a way I can check if memory is accessible before attempting the memcpy, or is there another protection mechanism to prevent the crash here? Would not checking **a cause a crash as well in this case?

Deepanjan Mazumdar
  • 1,447
  • 3
  • 13
  • 20
  • memcpy(&c, b, sizeof(int*)); – mf_ Jun 03 '13 at 18:51
  • 4
    @mf_ Nah, that's wrong. –  Jun 03 '13 at 18:52
  • @H2CO3 he is trying to copy a memory address to c, but c is not a pointer – mf_ Jun 03 '13 at 18:53
  • 4
    @mf_ Nah, that's wrong too. He's trying to copy an `int` from `b` to `c`. –  Jun 03 '13 at 18:54
  • @H2CO3 then the answer relies on checking **a for garbage ? – mf_ Jun 03 '13 at 19:02
  • @mf_ Which answer? Mine? No. I only answered what OP asked - he wants to know if `b` (a. k. a. `*a`) points to a valid memory location. –  Jun 03 '13 at 19:03
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/31145/discussion-between-mf-and-h2co3) – mf_ Jun 03 '13 at 19:05
  • Window's specific, but the same topic: http://stackoverflow.com/questions/993324/how-to-check-if-a-pointer-is-valid – Mike Jun 03 '13 at 19:32
  • If `*a` is NULL, this code uses `b` without initializing it. Is that representative of your real code? If so, your real code is broken; `b` should always be initialized before its use in `memcpy`, or the `memcpy` should not be performed. If not, then you have not shown us representative code. – Eric Postpischil Jun 03 '13 at 19:32
  • possible duplicate of [Checking if a pointer is allocated memory or not](http://stackoverflow.com/questions/1576300/checking-if-a-pointer-is-allocated-memory-or-not) – Mike Jun 03 '13 at 19:34

2 Answers2

2

There is no, portable way, to programmatically test if a pointer is pointing to valid accessible memory.

This is one reason for the highly recommended practice of always setting your pointers to NULL when the memory they were pointing to was freed and at initialization, so you have something to test against.

Would not checking **a cause a crash as well in this case?

Correct, all you're doing here is assigning the passed-in value to a local variable then attempting to access it. If the local is bad, it's because the passed-in value is bad. Garbage in, garbage out.


To address the code you provided:

   if (*a) {
       b = *a;
   }
   memcpy(&c, b, sizeof(int));//you really shouldn't be executing this at all unless
                              // you're setting b, so it should be within the if check 
                              // and only executed after b=*a
Deepstop
  • 3,627
  • 2
  • 8
  • 21
Mike
  • 47,263
  • 29
  • 113
  • 177
  • 1
    Voted down for ignoring the elephant in the room: The code in the question uses `b` without initializing it. This could be the cause of the initial problem. – Eric Postpischil Jun 03 '13 at 21:36
  • 1
    @Eric - a few points: 1) since the OP stated this was not the actual code it's more like "the elephant in the hallway", we don't know if the actual code has the same problems. 2) even if the code was within the check for setting b, there's no guarantee that it won't cause the problem. As you said, if `*a` is `NULL` `b` won't be set, but if `a*` is garbage, then `b` will be set and we'll still very likely crash in the `memcpy` 3) points 1 & 2 being said, you are correct that the code could be cleaner, so I addressed that. – Mike Jun 04 '13 at 02:49
0

If someone passes you a garbage pointer in *a there's no way of checking (not platform independent anyway) if that can be accessed.

But if someone is passing a==NULL or *a==NULL you could at least check for that (Eric mentioned that first in his comment to the other answer):

void func_foo(int **a) 
{
   int *b= NULL, c;

   if (a!=NULL) {
       b = *a;
   }

   if (b!=NULL) {
       printf("about to access memory at address 0x%p\n", b);
       memcpy(&c, b, sizeof(int));//this crashes because address "b" is not accessible.
       // btw same as c= *b  or  c= **a; 
   }
   else {
       printf("someone passed us a null pointer either in a or *a\n");
   }
}

Just for fun, a simplified version would be:

void func_foo(int **a) 
{
   int c;

   if (a!=NULL && *a!=NULL) {
       c = **a;
   }
   else {
       printf("someone passed us a null pointer either in a or *a\n");
   }
}
Nicholaz
  • 1,419
  • 9
  • 11