0

I have a pointer to char pointer in a struct. so there is a struct poiter object that I will pass to thread but thats not relevant.

so this is my struct

struct shard
{
    sem_t *semaphore_o;
    char **input;
    char **image_o;
};

I am creating object like

struct shard *obj=malloc(sizeof(struct shard));

and I am allocating the input in shard struct

*(obj->input)=malloc(sizeof(char)+1);

but abocve line giving segFault

user786
  • 3,902
  • 4
  • 40
  • 72

1 Answers1

2

*(obj->input) dereferences input before input points to valid memory, invoking undefined behavior, where manifesting with a segfault is common. You first have to malloc memory for it before dereferencing. You don't provide enough details about what you're trying to do, but something like:

struct shard *obj=malloc(sizeof(struct shard));
if (obj == NULL)
{
  // handle error how you want, and make a check like this for every malloc
  exit(-1);
}

obj->input = malloc(howManyCharPtrsYouWant * sizeof(*(object->input));
for (int i=0; i<howManyCharPtrsYouWant; i++)
{
  obj->input[i] = malloc(howManyCharsYouWant); // sizeof(char) is guaranteed to be 1, so no need to include it in `malloc`
}

See my previous answer for an explanation of sizeof(*(object->input)) if you're unsure what's happening there.

*(obj->input)=malloc(sizeof(char)+1); only allocates space for 2 chars (sizeof char == 1, +1 == 2 total). This is the smallest possible string you can have in C, one char followed by a NUL terminator. So if you're trying to put more than 2 chars in that buffer, that's an overflow --> UB --> possible segfault. If all you need is one char, better to bypass the malloc and simply use char c;, for example.

This is getting off topic, but the top two reasons you need dynamic memory allocation IMO are:

  1. You won't know how much memory you'll need until runtime
  2. You need "a lot" of memory (on your regular vanilla PC, I'd put this around 4+MB, but of course your mileage may vary depending on your needs and system).

SO has some good questions weighing the benefits of when to malloc or not, you can look them up.

If you know at compile time you'll need a max of 30 strings, only 30 chars long for example, then you can do something like

struct shard
{
    sem_t *semaphore_o;
    char input[30][30];
    // .. etc
};

and

struct shard obj; // you only need one of these, malloc makes little sense IMO
obj.semaphore_o = malloc(..); // this doesn't need to be a pointer either
strcpy(input[0], "hello there"); // fits in 29 chars plus NUL
strcpy(input[5], "I'm Jim");     // same

My preference is always to use automatic (stack) storage when possible, it's simpler because it relieves you of the burden of memory management.

yano
  • 4,827
  • 2
  • 23
  • 35
  • thanks for answer please see the full code I posted in question update, In a thread its giving me warning that `format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char **’ [-Wformat=] 58 | scanf("%s",((obj->input)));` – user786 Dec 04 '21 at 09:02
  • 2
    should I do `scanf("%s",(*(obj->input)));` – user786 Dec 04 '21 at 09:03
  • @user786 yes that's correct, the `"%s"` format specifier for `scanf` expects a `char*`, and that's what `*(obj->input)` is (`obj->input` is a `char**`). That means `"%s"` expects a `char` pointer to _at least two_ `char`s because you must leave room the `NUL` terminator. Just be wary of buffer overruns using pure `"%s"`, have a look [here](https://stackoverflow.com/questions/12306591/read-no-more-than-size-of-string-with-scanf) for a discussion about limiting input with `"%s"`. – yano Dec 04 '21 at 16:27
  • is there a neat way to pass pointer to pointer as thread parameter. I do not want to have contrainer struct because want to allocate parameter in thread and use it in parent thread whats allocated in child thread? Doable? – user786 Dec 04 '21 at 17:13
  • 1
    @user786 That's an entirely different question, but sure, if I understand correctly. The threading library I use in C is pthreads. When you create a function for the thread to execute, it accepts a `void*`, which is a pointer to any data type. So if you want to pass a `char** myDblPtr;` for instance, it would be like `pthread_create( ..., &myDblPtr,..);`. Then in the function you need to cast the argument from `void*` back to your data type: `char** myDblPtr = (char**)threadArg;`. Look at pthread argument passing and ask a new question if still confused. – yano Dec 04 '21 at 18:08
  • Sounds good will ask. – user786 Dec 05 '21 at 03:19
  • @user786 I told you wrong, that would be `pthread_create( ..., myDblPtr, ..);`, but yeah just ask a new question if you haven't already. – yano Dec 05 '21 at 05:42