Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C - Malloc and memcpy (memory management)

I'm a bit new to C and I'm having trouble understanding how memory works, especially in-built functions like memcpy.

Here's a struct I'm using

 struct data_t {
    int datasize;   
    void *data; 
 };

And here's an auxiliary function that I'm using it with:

struct data_t *data_create(int size)
{
   struct data_t *dt=malloc(sizeof(struct data_t)+size);
   dt->datasize=size;   
   dt->data="1234567890a";
   return dt;
}

Now in the main function I have no problem doing this:

struct data_t *data = data_create(1024);
data->data="123456a";//just an example

But this throws a Seg Fault:

memcpy(data->data,"123456a",strlen("1234567890a")+1);

My question is why? And how do I avoid it? Please bear in mind I'm new to C so how C deals with memory is a bit new to me

Thank you.

Edit: It works! Thank you very much. Completly missed the data pointer. Now everything is working fine according to valgrind.

like image 353
PTdude Avatar asked Oct 08 '11 17:10

PTdude


People also ask

How does malloc work in memory?

In C, the library function malloc is used to allocate a block of memory on the heap. The program accesses this block of memory via a pointer that malloc returns. When the memory is no longer needed, the pointer is passed to free which deallocates the memory so that it can be used for other purposes.

Why use memcpy in c?

In the C Programming Language, the memcpy function copies n characters from the object pointed to by s2 into the object pointed to by s1. It returns a pointer to the destination. The memcpy function may not work if the objects overlap.

When should memcpy be used?

The function memcpy() is used to copy a memory block from one location to another.

How to allocate memory dynamically in python?

Dynamic memory allocation is mostly a non-issue in Python. Everything is an object, and the reference counting system and garbage collector automatically return memory to the system when it is no longer being used.


1 Answers

memcpy(data->data,"123456a",strlen("1234567890a")+1);

fails because data->data a void * type points to some garbage/invalid address which is not allocated. data has the address of the string literal which is stored in the readonly section (like in the .rodata of the executable and loaded in the memory, which is not writable. Also, if you did not assign such a string address to the pointer variable, then it would hold some invalid/garbage address value which is not allocated or initialized with some valid permitted location. So first allocate the buffer.

data->data = malloc (sizeof (char) * size);

The malloc will return the first location address of a block of address of atleast size * sizeof (char) bytes. Now you can copy size bytes to this memory location pointed by data->data.

Remember to free the allocated memory block when you have finished working with that memory bock with the free (addr) call.


I see you have tried to allocate data buffer with a very strange manner (?):

struct data_t *dt=malloc(sizeof(struct data_t)+size);

for which the extra allocated size bytes along with the struct data_t. But what ever be the case, data component still points to some place which cannot be changed. Please use:

struct data_t *dt = malloc(sizeof(struct data_t));
dt->data = malloc (sizeof (char) * size);
memcpy (data->data, "whatever", sizeof ("whatever")+1);
return dt;

to free first do:

free (dt->data);

then

free (dt);
like image 77
phoxis Avatar answered Oct 17 '22 15:10

phoxis