2

I want to allocate some memory to a pointer using a function. Following is the code I have written:

#include <stdio.h>
#include <stdlib.h>

int test( unsigned char **q)
{
    *q = (unsigned char *) malloc(250);
    if(*q == NULL)
    {
        printf("\n Error: failed to allocate memory");
        return -1;
    }   
//  *q[0] = 10;
//  *q[1] = 10;
    *q[2] = 10;

    return 0;   /* Returns 0 on success, non-zero value on failure */
}

int main(void)
{
    unsigned char *p;

//  printf("\n &p = %u", &p);
    int result = test(&p);  

//  printf("\n p[2] = %d", p[2]);
    return 0;
}

If I write something in *q[0] or *q[1], there is no error. But when I try to write something to *q[2], it gives "Segmentation fault (core dumped)".

Also I'm getting all data as 0 using p[ ] except p[0].

What is wrong with this code?

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
mk09
  • 313
  • 2
  • 9
  • 2
    Welcome to Stack Overflow! [Please see this discussion on why not to cast the return value of `malloc()` and family in `C`.](http://stackoverflow.com/q/605845/2173917). – Sourav Ghosh Jan 31 '17 at 10:36
  • 6
    `*q[2] = 10;` should be `(*q)[2] = 10;`. – mch Jan 31 '17 at 10:36
  • Lack of knowledge != Typo. Voting to Reopen. Feel free to close as dupe. – Sourav Ghosh Jan 31 '17 at 10:48
  • Yes.. this was a mistake due to ignorance. Also this was the first time I dealt with memory allocation inside the function and returning it. Thanks for instant answers. – mk09 Jan 31 '17 at 11:49

3 Answers3

2

Due to the absense of explicit parenthesis and thus, default operator precedence coming into effect, your expression is interpreted wrongly.

For an expression like

 *q[2]

it is interpreted as

*(q[2])

which is what you don't want here. Pointer arithmetic honors the data type, so, x + 1 or x[1] will have different results, when

  • x is type char *
  • x is of type char **.

You need to write

 (*q)[2] = 10;

explicitly, first to dereference the q to get the char *, and then , use the indexing to get the char.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
2

Due to operator precedence of C language, for *q[2], [] operator is evaluated before * operator.

So *q[2] is the value at address q + 2. What you want is value at *q + 2. So use (*q) + 2.

*q[0] or *q[1] did not give segmentation fault because addresses q + 0, q + 1 have been allocated to your process.

Address q + 2 was not allocated to your process and hence the segmentation fault.

David Ranieri
  • 39,972
  • 7
  • 52
  • 94
Ashish kulkarni
  • 644
  • 2
  • 7
  • 13
  • Thanks. Your answer explains reasoning for all the errors I got. Vlad from Moscow gave different ways to avoid these errors. So I accepted that answer. – mk09 Jan 31 '17 at 11:58
0

Instead of this wrong assignment

*q[2] = 10;

that is due to the operator precedence equivalent to

*( q[2] ) = 10;

and as result the dereferenced pointer q[2] is uninitialized and has indeterminate value. You should write either like

( *q )[2] = 10;

or even just like

q[0][2] = 10;

Another way is to introduce an intermediate variable and use it to initialize elements of the array. For example

char *p = *q;

p[2] = 10;

This allows to escape that kind of errors with pointers.

mk09
  • 313
  • 2
  • 9
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335