Your first mistake is this:
struct data_t *dt=malloc(sizeof(struct data_t)+size);
This will create a chunk of memory of size struct data_t + size. I think what you expected was that your data field inside data_t could use this memory but it cannot because data does not hold an address to this memory.
Your second mistake was to assume that you where copying the value of the following string into "data":
data->data="123456a";
What in fact happened here is that there is a string in memory "123456a" that exists for the entire life of your program. When you assign "123456a" to data->data what is actually happening is that you are taking the address of this string "123456a" and putting it in data->data you are not copying the value ("123456a") but the location or address (0x23822...) of "123456a" .
Your final mistake was this:
memcpy(data->data,"123456a",strlen("1234567890a")+1);
You tried to copy the value "123456a" into memory pointed to by data. What is data pointing to? It's pointing to a read only area of memory containing your previously assigned string "123456a". In other words you told your program to write to the address of "123456a".
Here is a program what will do what you expect:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
typedef struct {
size_t datasize;
char *data;
} data_t;
data_t *data_create(size_t size)
{
data_t *dt;
dt = malloc(sizeof(data_t));
assert(dt != NULL);
dt->data = malloc(size);
assert(dt->data != NULL);
dt->datasize = size;
/* need to decide what to do when this happens */
assert((strlen("1234567890a") + 1) < size);
strcpy(dt->data, "1234567890a");
return dt;
}
void data_destroy(data_t *dt)
{
free(dt->data);
free(dt);
}
int main(void)
{
data_t *data = data_create(1024);
/* data->data="123456a"; DONT DO THIS YOU WILL CAUSE A MEMORY LEAK */
assert(data->datasize >= (strlen("123456a")+1));
memcpy(data->data, "123456a", strlen("123456a")+1);
printf("%s\n", data->data);
data_destroy(data);
return EXIT_SUCCESS;
}