-1

I've looked through topics of similar kind, but didn't find a solution for my problem. I've got a struct like

typedef struct {
    int number;
    char *string;
} mystruct;
    
//Then define a pointer to the struct:
mystruct *data;
    
// Allocate memory:
data = malloc(sizeof(mystruct));
    
//Assign some number, let's say 5:
(*data).number = 5;
    
//So far ok, works (checked: 5 can be retrieved from the struct somewhere else) but:
    
strcpy((*data).string = "Hello!");
//This line fails with segmentation fault.

I don't understand why? Can somebody please explain what I'm doing wrong?

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
rebit
  • 51
  • 5
  • Because member `char *string;` also needs a memory allocation to copy a string. But you can do `data->string = "Hello!"` to assign the pointer. – Weather Vane Dec 09 '21 at 23:04
  • 3
    `strcpy()` needs two arguments. – Barmar Dec 09 '21 at 23:04
  • When you write your question, please use the correct tools in the editor to format text as code. It's far more effort to insert HTML line breaks than it is to highlight the code and press the `{}` button. And the latter will actually produce something that doesn't burn our eyes. – paddy Dec 09 '21 at 23:04
  • 3
    BTW, we normally write `pointer->member` rather than `(*pointer).member` – Barmar Dec 09 '21 at 23:05
  • 1
    I suspect you actually write `strcpy((*data).string, "Hello!");`, otherwise it wouldn't even compile. In that case, see @WeatherVane's comment. – Barmar Dec 09 '21 at 23:07
  • `strcpy((*data).string = "Hello!");` should fail to compile -- if you are not seeing an error message, adjust your compiler settings – M.M Dec 10 '21 at 01:27
  • Yes, sorry very much for all the typos. I've been really, really tired yesterday, just typed and went to sleep. :) Actually, strcpy argument is, of course, with semicolon, not assignment, and even the string in struct is fixed length ([256]), so memory allocation inside the struct should be obsolete... . Doesn't work anyway – rebit Dec 10 '21 at 06:50
  • Found the problem: in a corresponding header, a function argument was missing and the compiler didn't complain.... . The rest is ok and the world is right again. I'm not cursed ;) – rebit Dec 10 '21 at 07:10

3 Answers3

3

As mentioned in the comments, the problem with your attempted strcpy call is that your destination (the string member of your data) isn't a pointer to valid memory. (I am assuming that your invalid syntax, strcpy((*data).string = "Hello!") is a typo, and that your real code has something like strcpy((*data).string, "Hello!") – otherwise, it won't even compile, so you won't get a segmentation fault.)

There are several approaches to fix this, depending on what you actually want to happen. First, as also mentioned in the comments, you can just copy the pointer to the destination, like this1:

data->string = "Hello!";

However, this may not be what you want, because, if the source is not actually a literal, but a modifiable string, then, after that assignment, any changes to the source will also apply to your copy.

If you want a copy of the source data, you will need to allocate sufficient space for it, then call strcpy; like this:

#include <stdlib.h> // For malloc

const char* src = "Hello!";
data->string = malloc(strlen(src) + 1); // Add 1 for the required nul-terminator
strcpy(data->string, src);

However, the strdup function2 does the job of the above malloc and strcpy calls in one fell swoop:

data->string = strdup("Hello!");

In each of the above two cases, be sure to call free(data->string) when you're finished.


1 Note that you can use the "member access through pointer" (->) operator, rather than dereferencing and then using the . operator: data->number = 5 is equivalent to your (*data).number = 5.

2 Some compilers/platforms may not support the strdup function, but it is part of the ISO C Standard from C23

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
  • Hi Adrian, thanks for your long answer. IN fact, the problem was different, pls see comment to original post. – rebit Dec 10 '21 at 07:06
0

I am not sure to understand this line

strcpy((*data).string = "Hello!");

Do you mean

strcpy((*data).string, "Hello!");

I believe the issue is that your struct contain a pointer char * string that doesn't point to a valid allocated memory. You can try multiple solutions

  1. Have struct with predefined size
typedef struct {
    int number;
    char string[100];
} mystruct;

  1. You can allocate memory for the string during the initialization
data = malloc(sizeof(mystruct));
data->string = malloc(sizeof(char) *100));

S_F
  • 19
  • 3
0

As other users mentioned, you need to allocate space for the string.

I would use a flexible array member and have only one allocation for the struct and string.

typedef struct {
    int number;
    char string[];
} mystruct;


mystruct *create(const char *str)
{
    mystruct *ms = NULL;

    if(str)
    {
        ms = malloc(sizeof(*ms) + strlen(str) + 1);
        if(ms)
        {
            strcpy(ms -> string, str);
            ms -> number = 0;
        }
    }
    return ms;
}

int main(void)
{
    mystruct *ms = create("Hello");

    if(ms)
    {
        printf("ms -> string = `%s`\n", ms -> string);
    }
    free(ms);
}
0___________
  • 60,014
  • 4
  • 34
  • 74