I have written a code which at first creates a memory alloc and save a string in an other pointer. According to the code, the value must be kept in an other address after free but it gives an error "munmap_chunk(): invalid pointer".
My Code is :
#include <stdio.h>
#include <stdlib.h>
#include "testfunc.h"
#include <string.h>
int main()
{
static char *server_alg;
char *test;
char *test = (char*) malloc(30*sizeof(char));
server_alg = "A";
strcpy(test, server_alg);
printf("server_alg addr = %u \n", &*server_alg);
printf("server_alg value = %u \n", server_alg);
printf("SERVER_ALGO addr = %d \n", *server_alg);
free(server_alg);
server_alg=NULL;
printf(" nulled \n");
printf("server_alg addr = %u \n", &*server_alg);
printf("server_alg value = %u \n", server_alg);
printf("SERVER_ALGO addr = %u \n", test);
printf("SERVER_ALGO value = %u \n", *test);
return 0;
}
Is it wrong?
Thx for your helps
You are freeing server_alg, but you didn't allocate any memory there. Instead, you assigned a string literal to it, so it's pointing to a read-only location in your program's binary:
server_alg = "A";
After this, you copy from that pointer to test:
strcpy(test, server_alg);
This is correct, as you properly allocated memory for test here:
char *test = (char*) malloc(30*sizeof(char));
Then, however, you try to free it while it is still pointing to "A" in your binary:
free(server_alg);
Instead, try freeing test, because that is pointing to the memory you allocated:
free(test);
test=NULL;
Furthermore, there's an issue with redeclaration here:
char *test;
char *test = (char*) malloc(30*sizeof(char));
You're defining test twice, best just remove that first line.
Last but not least, I'd change the prints in the end to:
printf("server_alg addr = %p \n", server_alg); // 00D87B30 (or something similar)
printf("server_alg value = %s \n", server_alg); // A
printf("SERVER_ALGO addr = %p \n", test); // 00000000
//printf("SERVER_ALGO value = %u \n", *test);
%s is the specifier that lets you print a string, and %p is the one for pointers. I commented out that last print because it would crash the program as test is freed and set to a null pointer now, so we can't access its content.
On another note, when you want to copy a string to the heap (be it from a string literal or from a different place on the stack heap), strdup can be used to do that. It allocates the appropriate amount of memory so you don't have to worry about that. Call it like this:
char *test = strdup("A");
When you're done with it, you free it by calling free(test);, just like with memory allocated by malloc.
following statements are the issues here
free(server_alg);
you can use free() only when if you allocate memory using one of malloc(), calloc() or realloc() as you have not allocated memory free(server_alg); is wrong, it will lead to memory dump
and we should never try to use pointer once we do free() on it.
Related
I have below code where I have commented when I get segmentation fault and when not.
Originally I got segmentation fault and then I could figure out that probably I cannot initialize my char pointer locations like "abcd". But I am not able to understand - WHY?
I thought testString = "abcd"; will put a at first memory address, b at second and so on ...
Segmentation fault occurs when trying to free memory, based on how I initialize memory location.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char* testString = malloc(sizeof(char) * 5);
printf("Size of char is: %d\n", sizeof(char));
printf("Size of int is: %d\n", sizeof(int));
for(int i = 0; i < 5; i++)
{
printf("Pointer addresses are: %p\n", testString + i);
}
char* tempPtr = testString + 2;
printf("My temp pointer address = %p\n", tempPtr);
// This gives me segmentation fault ....
testString = "abcd";
// This will not give me segmentation fault ....
//int count = 65;
//for(int i = 0; i < 5; i++)
//{
// testString[i] = count + i;
//}
printf("Printing character...\n");
for(int i = 0; i < 5; i++)
{
printf("Characters are: %c\n", testString[i]);
}
printf("Freeing memory...\n");
free(testString);
//printf("Access after freeing >>%c<<\n", tempPtr[0]);
//free(testString);
}
Based on #M.M. and #Jonathan's comment I understood that with testString = "abcd"; my testString will point to a memory location where string "abcd" was created and since I didn't malloc'ed it I cannot free it. Also, since my original pointer to heap memory (which I got using malloc) is gone, so it is waste of memory or memory lead.
So, does it means that when I use printf statement like printf("Printing character...\n");, this is also a memory leak? Then how do I avoid it? Looping and inserting into char* is certainly a bad idea.
this line:
testString = "abcd";
is overlaying the pointer given by the call to malloc() with the address of the string literal: "abcd" this results in a memory leak because the original pointer to the allocated memory is lost.
In C, when copying a string, it 'should' be handled by the functions: strcpy() and strncpy() which will not corrupt the pointer contained in testString.
strcpy( testString, "abcd" );
strncpy( testString, "abcd", strlen( "abcd" ) );
Naturally, once the pointer to the allocated memory has been overlayed/destroyed by the assignment statement: testString = "abcd";, the new value placed into testString must not be passed to free()
the seg fault would be happening at the call to free(), not at the incorrect assignment of a new pointer to testString.
Using printf is not a memory leak. Memory leaks occur when a pointer is allocated via malloc [or, herein, strdup] and there is no corresponding free call for it.
Also, trying to free a pointer that has not been allocated is another type of error. It [probably] won't segfault, but free will complain.
Here's a simplified version of your program that illustrates some of the ways you can do this:
#include <stdio.h>
#include <string.h>
#include <malloc.h>
int opt_segv;
char *temp = "abcd";
void
dostr(char *str,int modflg)
{
printf("\n");
printf("dostr: %s\n",str);
if (modflg)
str[modflg] = 'm';
printf("dostr: %s\n",str);
}
void
test1(void)
{
int len;
char *testString;
len = strlen(temp);
testString = malloc(len + 1);
strcpy(testString,temp);
dostr(testString,1);
free(testString);
}
void
test2(void)
{
char *testString;
testString = strdup(temp);
dostr(testString,2);
free(testString);
}
void
test3(void)
{
char *testString;
// passing a pointer to a string _constant_ -- do _not_ modify
testString = temp;
dostr(testString,opt_segv ? 3 : 0);
}
int
main(int argc,char **argv)
{
char *cp;
--argc;
++argv;
for (; argc > 0; --argc, ++argv) {
cp = *argv;
if (*cp != '-')
break;
switch (cp[1]) {
case 's': // generate segfault
opt_segv = 1;
break;
}
}
test1();
test2();
test3();
return 0;
}
You can run the program with -s to simulate the string constant modification that caused your segfault.
This question has content relevant to answer of my question but doesn't have detailed answer. #Jonathan's comments answers all my questions but he hasn't put forward a detailed answer so I am writing my answer so that folks who will visit further can have detailed explanation:
I created a pointer and allocated some space on "heap segment" of the memory, now my pointer was pointing to that memory location on heap.
Code relevant for all this is - char* testString = malloc(sizeof(char) * 5);.
Now, when I dis this - testString = "abcd"; then string "abcd" is created in "text/code segment" (or in some implementation data segment) of the memory and memory address is returned and assigned to my pointer testString.
What happens is that my original pointer which was pointing a memory location on heap is lost and the pointer started pointing to a memory location on text/code segment of the memory.
Implication of all this:
It has resulted in memory leak because my original pointer which was pointing to the heap memory is lost, so now I have no way to free that heap memory and hence memory leak.
When I will try to free that memory using free(testString); then I will get segmentation fault (this is exactly what has happened to me) because free() can only be used to free the memory which is allocated using either malloc, calloc or realloc. Now, since the pointer testString is pointing to a memory location on text/code segment and I had not allocated that memory using some C memory allocation method, so I cannot free it using free() and if I do so then I get segmentation fault.
When I do testString = "abcd" (when testString is a pointer) then I cannot access the memory location pointed by testString because the memory allocated is read-only in text/code segment of the memory. So, testString[0] = 'x' will also result in segmentation fault.
What happens when I do printf("hello, world")?:
This will create "hello, world" string as read-only in text/code segment of memory. I verified that it does create in text/code segment in C99 implementation using size command.
I have this code snippet to understand the memory management function void free(void*) in C. What I know about free function is that it will deallocate the memory that is managed by a pointer. I want to see what will happen after a block of memory is set free and whether the pointer associated is still accessible to that block of memory.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STR_SIZE 20
int main(int argc, char *argv[])
{
char originalChar [] = "123456789";
char *myChar = (char*) malloc(sizeof(char) * STR_SIZE);
if (!myChar) {
printf("allocation failed!");
exit(1);
}
char *isOk = strncpy(myChar, originalChar, STR_SIZE*sizeof(char));
if(!isOk) exit(1);
char *myCharCopy = myChar;
printf("oC = %d, mCC = %d; mC = %d\n", originalChar, myCharCopy, myChar);
printf("The strings = %s\n", myChar);
printf("The strings = %s\n", myCharCopy);
free(myChar);
printf("----- free happened here -----\n");
// myChar = NULL;
printf("oC = %d, mCC = %d; mC = %d\n", originalChar, myCharCopy, myChar);
printf("The strings = %s\n", myChar);
printf("The strings = %s\n", myCharCopy);
return 0;
}
Then, I got those results from its output.
oC = 1482066590, mCC = 826278544; mC = 826278544
The strings = 123456789
The strings = 123456789
----- free happened here -----
oC = 1482066590, mCC = 826278544; mC = 826278544
The strings = 123456789
The strings = 123456789
This result makes very little sense to me. Because free function is supposed to set free the block of memory but it is NOT from the result. What on earth happened here? Besides, it seems the pointer associated with the memory on heap is still accessible to that freed memory. Why this will happen since it is freed?
As per the C11 standard, chapter ยง7.22.3.3, The free function
The free function causes the space pointed to by ptr to be deallocated, that is, made
available for further allocation.[..]
It does not mandate that the pointer would be set to NULL (or anything else, for that matter). free()-ing is just an indication to the OS that the allocated memory can be reclaimed and reissued, as and when required.
Accessing free()-d memory is undefined behavior. So, once free() is called, you should not be accessing the pointer anymore.
For this very reason, it is often considered a good practice to set the free()-d pointer to NULL immediately after the call to free() so that to avoid any unintended access to already freed memory.
That said,
printf("oC = %d, mCC = %d; mC = %d\n", originalChar, myCharCopy, myChar);
also invokes undefined behavior. %d is to print an int, not a pointer (or string, for that matter). In case you want to print the address, you may want to use
printf("oC = %p, mCC = %p; mC = %p\n", (void*)originalChar, (void*)myCharCopy, (void*)myChar);
Per the C standard:
7.22.3.3 The free function
...
The free function causes the space pointed to by ptr to be
deallocated, that is, made available for further allocation. If ptr
is a null pointer, no action occurs. Otherwise, if the argument does
not match a pointer earlier returned by a memory management function,
or if the space has been deallocated by a call to free or realloc , the behavior is undefined.
But now your code accesses the memory, which invokes undefined behavior, per the C Standard again:
J.2 Undefined behavior
1 The behavior is undefined in the following circumstances:
...
The value of a pointer that refers to space deallocated by a call to
the free or realloc function is used (7.22.3).
Including appearing to "work".
I want to print out things from given memory addresses.
Using this code, I can define a variable, define a pointer to it and print its contents using the pointer.
char buf[100];
void *p = buf;
strcpy(p, "Test string");
printf("Address: %X\n", &buf);
printf("Contents: %c\n", p);
What I want to do is to specify a certain memory address, and print out the contents of that block. I tried experimenting by incrementing and decremeting p, but it doesn't print out anything.
An interesting little problem. One that should occur to every programmer sooner or later, either out of curiosity or cussedness.
Essentially four parts.
Express the address you want as an integer of the appropriate size.
Cast the integer into a pointer to some type.
Dereference the pointer to get a value of that type.
Print the value.
[if desired, increment address and repeat.]
For simplicity I'll use an address of 0x1000 and integer contents.
int address = 0x1000;
int* pcontent = (int*)address;
int content = *pcontent;
printf ("Address %p: content %08x\n", pcontent, content);
Two points should be made.
This is undefined behaviour, but inevitable if you want to get a result.
The address I chose could be valid memory or could trigger a trap error or it could do just about anything. You'll have to experiment with different addresses to find out which.
[Many years ago I used this strategy to print out the entire contents of memory on a machine that had just 96KB of memory, which led to some interesting hacking possibilities. But I digress.]
You are using wrong specifier to print the address. Use %p and cast argument to void *.
printf("Address: %p\n", (void*)buf);
and to print string
printf("Contents: %s\n", p);
You have to define pointer p as
char *p = buf;
or to use casting then incrementing p. For example
p = ( char *)p + n;
For example
printf( "%s\n", ( char *)p + 5 );
You may not increment/decrement pointers of type void * because void in incomplete type.
Also the format specifiers in these calls
printf("Address: %X\n", &buf);
printf("Contents: %c\n", p);
are wrong.
If you want to print out a string you have to specify %s. if you wnat to print only one character then you should write
char *p = buf;
printf("Contents: %c\n", p[0]);
or
void *p = buf;
printf("Contents: %c\n", ( ( char *)p )[0]);
You are using %c instead use %s to print string printf("Contents: %s\n", p);
If we wanted to print random bytes from around memory, we would want to use:
char *p = buf;
printf("Address: %p\n", p);
printf("Contents: 0x%02x\n", *p);
Let's note though, that given a random address, dereferencing it can cause the application to fail. You can not assume that all of the memory space is valid.
You could try something like this:
void printMemory(void* mem, int bytes){
char* p = (char*) mem;
for(int i=0;i<bytes;i++){
printf("%x ",p[i] & 0xff);
if(i%8 == 7)
printf("\n");
}
}
This will print 8 bytes per row.
According to this question: When should I use malloc in C and when don't I?
Using malloc to allocate memory should allow me to change one of the characters in the array. However, this program crashes at run time. Can someone please advise? (also free(ptr) causes a different crash which is why it is commented out).
char* ptr;
ptr = (char *)malloc(sizeof(char[10]));
ptr = "hello";
ptr[0] = 'H';
printf("The string contains: %s\n", ptr);
//free (ptr);
return 0;
Your program crashes because this line
ptr = "hello";
completely undoes the effect of malloc from the previous line:
ptr = malloc(sizeof(char[10])); // No need to cast to char*
and it also creates a memory leak along the way, because the address returned by malloc is irrecoverably lost after the assignment.
Once the assignment is done, an attempt to set ptr[0] = 'H' results in a crash, because you are trying to modify the memory of the string literal itself - i.e. undefined behavior.
In C strings need to be copied, not assigned if you want to modify them later. Replace the assignment with strcpy call to fix this problem.
strcpy(ptr, "hello");
There are several things that need to be fixed:
char* ptr = 0;
ptr = (char *)malloc(sizeof(char)*10);
if(!ptr)
return 0; // or something to indicate "memory allocation error"
strcpy(ptr, "hello");
ptr[0] = 'H';
printf("The string contains: %s\n", ptr);
free (ptr);
return 0;
This compiles and runs correctly in main()
To learn more about pointers I wrote just a simple test function which creates a pointer, allocates space ande after some output on the shell the space shall be freed.
void main() {
int *p = (int*) malloc(sizeof(int));
int a = 42;
printf("p: %x\n", p);
printf("*p: %d\n", *p);
printf("a: %s\n", a);
printf("&a: %x\n", &a);
p = &a;
printf("p: %x\n", p);
printf("*p: %x\n", *p);
//Until now everything works as expected
free(p); //ERROR
// printf("p: %x\n", p); // Shall cause error, because space was freed
// printf("*p: %x\n", *p); // Shall cause error, because space was freed
}
At first runs everything was ok. free(p) caused no error. Then I tried the same test with a struct and got the double free error. "Ok, maybe I do something wrong, lets go to the start", I thought and Ctrl+Z everything to this one above, like it was before. Now I still get this error. Why? Thats a newbie question, I know. The code above you can find everywhere in the web as a simple demonstration of malloc and free. Like here: http://www.cplusplus.com/reference/cstdlib/free/
Hope, someone can tell me what I do wrong.
The pointer passed to free() must be returned from a previous call to malloc() (or calloc() or realloc()). This is not the case as p has the address of a after:
p = &a;
and p is then passed to free() causing undefined behaviour.
Note that in the example on page linked in the question nowhere is the pointer being reassigned after the call to any of the dynamic allocation functions.
The comment "Shall cause error, because space was freed" in the following code snippet is incorrect:
free(p); //ERROR
// printf("p: %x\n", p); // Shall cause error, because space was freed
as it is safe to print the address of a pointer, regardless of whether the memory it has been associated with has been free() or not. It is an error if you attempt to access memory that has been free()d, so this comment is correct:
// printf("*p: %x\n", *p); // Shall cause error, because space was freed
because p is being deferenced and an attempt to read free()d memory is occurring.
This is an error:
printf("a: %s\n", a); /* Must be '%d' as 'a' is an 'int'. */
Note that:
printf("p: %x\n", p);
is also undefined behaviour: use %p format specifier for pointers. See Correct format specifier to print pointer (address)?
Do I cast the result of malloc?
void main() {
int *p = (int*) malloc(sizeof(int)); // here is error number one.
// you casted your fresh malloc'd int
// to an int*
// which is not what you want to do
// get rid of the cast you don't need it.
// here is where your problem continues.
int a = 42; // this variable A was created on the stack not the heap!!
//you cant free this, which is what you are doing below.
printf("p: %x\n", p);
printf("*p: %d\n", *p);
printf("a: %s\n", a);
printf("&a: %x\n", &a);
p = &a; // this is a correct statement.
// you getting the address of var a
// and making pointer p point to A's contents.
printf("p: %x\n", p);
printf("*p: %x\n", *p);
//Until now everything works as expected
free(p); //ERROR: here you are trying to free var A
// but you cant because it wasnt dynamically allocated.
// printf("p: %x\n", p); // Shall cause error, because space was freed
// printf("*p: %x\n", *p); // Shall cause error, because space was freed
}
hope this helps a bit.
I highly recommend that you read CH 5 on pointer in K&R(Kernegie and Richie) C programming language book.
its really short and you can probly find it free online somewhere. in fact i recommond that you read the whole book. best c book out there.
remember you can only free what you malloced (remember each malloc gives you blocks in memory from the heap)