Home > Software engineering >  how do i copy a pointer to avoid a memory leak when operating on it?
how do i copy a pointer to avoid a memory leak when operating on it?

Time:11-28

I've taken the below code from one of the stack overflow posts: What does "dereferencing" a pointer mean?

Why does '''const char* q = p''' copy the pointer p to q such that when q is changed, p remains the same? it doesnt seem to make logical sense, const char* q should a store an address value of a char, it points to another pointer p. So instead, it points to an address, which stores another address, which is then the char

const char* p = asprintf("name: %s", name);  // Common but non-Standard printf-on-heap

// Replace non-printable characters with underscores....
for (const char* q = p; *q;   q)
    if (!isprint(*q))
        *q = '_';

printf("%s\n", p); // Only q was modified
free(p);

Tried debugging to no avail

CodePudding user response:

A pointer is, in short, a type (or value of said type) representing the address of a value of another type.

So when writing char* p; It means that p is the address of a value of type char. Andp is of type char* (pointer to char).

When copying a value in C, both the origin value and its destination containers shall be of the same type. When doing

char* p = /* some address value*/;
char* q = p; 

What char* q = p; does is to copy the value of p (so, the address) into the variable q.

So for example, if p contains value 0x0110, q will contain value 0x0110 as well. An address is not much more than an unsigned integer, so here the copy works exactly the same.

It does not create a pointer to a pointer, but copies the address.

Now digging in the code you mentionned (which seems a bit strange to me, not sure we are able to modify a const value in this context, but that's not the important thing here.):

When needing more memory during execution of a program, in C we can manually ask the system for memory. This is called a memory allocation. An allocation returns a pointer to the allocated memory. It is done with functions like malloc or asprintf.

When we don't need the memory anymore, we have manually tell the system we don't need memory anymore, this is called releasing the memory. It is done with functions like free. Those fonctions usually take the pointer returned by an allocation as a parameter, so we have to keep track of it.

/* asfprintf does an allocation of a 
string (say S) in memory, and returns a 
pointer pointing to the "beginning" 
of the memory space allocated */
const char* p = asprintf("name: %s", name);  
    
    
/* here, we iterate over all characters of the string S,
pointed to by p
To do so, we have to compute the value of each 
successive character's address in the string, 
and we do this by incrementing the pointer p. 
However, we do it on a working copy of the pointer, 
to remember the value of the start of the memory chunk 
where S is stored
*/
for (const char* q = p; *q;   q)
    if (!isprint(*q))
        *q = '_';
    
/*At this point, q has been incremented, 
and points to the last element of S, 
the terminating character, null-string.
Schematically, it looks like this
(0 is the string terminating character) : 
    
    name : the_na_me0
           |        |
           p        q

so here, when the comment below says "only q was modified", 
it means the address in p has not been changed, only the address 
in q has been incremented.
*/
printf("%s\n", p); // Only q was modified 
free(p); /*we can safely use p to release S's memory*/

I hope I have been clear, be sure to comment I you need clarification or more details.

  •  Tags:  
  • c
  • Related