munmap_chunk(): invalid pointer - c

I've spotted the error in my program and decided to write a simple one, which would help me understand what's going on. Here it is :
#include <stdio.h>
#include <stdlib.h>
char * first()
{
char * word = malloc(sizeof(char) * 10);
word[0] = 'a';
word[1] = 'b';
word[2] = '\0';
return word;
}
char * second ()
{
char * word = malloc(sizeof(char) * 10);
word = "ab";
return word;
}
int main ()
{
char * out = first();
printf("%s", out);
free(out);
out = second();
printf("%s", out);
free(out);
return 0;
}
The first() function is working properly, but the second() (exactly the free(out) ) genarates error:
Error in `./a.out': munmap_chunk(): invalid pointer: 0x0000000000400714 ***
ababAborted (core dumped)
I don't understand why the first function is correct, but the second isn't. Could anyone explain why?

In the function second(), the assignment word = "ab"; assigns a new pointer to word, overwriting the pointer obtained through malloc(). When you call free() on the pointer later on, the program crashes because you pass a pointer to free() that has not been obtained through malloc().
Assigning string literals does not have the effect of copying their content as you might have thought. To copy the content of a string literal, use strcpy():
strcpy(word, "ab");

In function char * second
char * word = malloc(sizeof(char) * 10);
word = "ab";
The second statement word = "ab"; changes word to point away from the allocated memory.You are not copying the string "ab" to the area of heap allocated by malloc.
And to free a memory that is not allocated by malloc or similar functions crashes your program.
Attempting to free an invalid pointer (a pointer to a memory block that was not allocated by calloc, malloc, or realloc) may affect subsequent allocation requests and cause errors.
You should use here strcpy as also suggested by others.

Related

Why don't I have to free heap objects when I pass them into a function?

The following program has no memory leaks. My question is, why does str1 and str2 not have to be passed into free(), even though I malloc'd both strings? Please see two commented locations in the code where I attempted to free str1 and str2, uncommenting that code resulted in an error saying I free'd a non-heap object. But from my understanding, str1 and str2 are objects created by malloc, hence are heap objects. I do not understand this contradiction.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* StrCat(char* s1, const char* s2) {
// Removing const from const char* s2
// made no difference on memory leak error message
char *s, *tmp;
s = tmp = malloc(strlen(s1) + strlen(s2) + 1);
strcpy(tmp, s1);
tmp += strlen(s1);
strcpy(tmp, s2);
//free(str1); free(str2); Why not?
printf("%d\n", s[strlen(s)] == '\0'); // Prints 1
return s;
}
int main(int argc, char** argv) {
char* str1 = malloc(4 * sizeof (char));
str1 = "abc\n";
char* str2 = malloc(6 * sizeof (char));
str2 = "party\n";
char* new = StrCat(str1, str2);
//free(str1); free(str2); Why not?
printf("%s\n", new);
free(new); // Required
return 0;
}
Of course you need to free heap objects, whether you pass them to a function or not. Whatever is returned by malloc() must eventually be free()d, regardless of how you will use it.
Your problem is as follows:
The following line:
char* str1 = malloc(4 * sizeof (char));
allocates memory for 4 characters and stores a reference to it in str1.
The following line:
str1 = "abc\n";
forgets whatever memory str1 was pointing to, (thus causing a memory leak,) and makes str1 point to a new location, in your program's static data segment. This is memory which was never allocated, and therefore may not be freed.
In order to solve your problem, instead of setting str1 to point to "abc\n" you need to use strcpy() to copy "abc\n" to the allocated memory block which is pointed by str1.
Before doing that, do not forget to increment your 4 and your 6 by 1 each, because strings in C also contain a null-terminating byte, so you need to allocate space for 5 and 7 characters respectively.

Segmentation fault in my strcpy

I'm writing my own strcpy due to the fact that the default one in string.h only accept a const char * as a source string to copy from.
I'm trying this very basic prototype (yes, the return isn't meaningful, I'm just trying things):
int copyStrings(char * dest, char * source){
int i=0;
while(source[i]!='\0'){
dest[i]=source[i];
i++;
}
dest[i]='\0';
return 0;
}
and it gives me SIGSEGV, Segmentation Fault error in gdb, at the line dest[i]=source[i], right at the first character. I'm pretty sure dest[i] isn't a string literal, so I should be able to modify it.
What am I doing wrong?
EDIT: here's the calling
int main(){
char * str = (char*)malloc((int)sizeof(double));
char * str2 = (char *)malloc((int)sizeof(int));
str = "hello";
str2 = "hey jude";
copyStrings(str2, str);
free(str);
free(str2);
return 0;
}
This is assigning a string literal to str2 - the very thing that you claim you aren't doing. This is actually the cause of your segfault.
str2 = "hey jude";
It also is causing a memory leak as prior to this, you malloc'd some memory and assigned it to str2 as well. But not enough memory to hold the string. Typically an int is 4 bytes and you need 9 bytes to store that string.
What you want to do is this, which allocates as many bytes as there are in the string, plus an extra one to store the \0 terminating character at the end.
str2 = malloc(strlen("hey jude")+1);
strcpy(str2,"hey jude");
or on some systems you can use POSIX function strdup() which effectively does the job of the above in one handy function call.
str2 = strdup("hey jude");
Let's go at it line by line and see where it goes wrong:
int main(){
char * str = (char*)malloc((int)sizeof(double));
char * str2 = (char *)malloc((int)sizeof(int));
str = "hello";
str2 = "hey jude";
copyStrings(str2, str);
free(str);
free(str2);
return 0;
}
int main(){ - this is an improper definition of main. Should be int main(int argc, char **argv)
char * str = (char*)malloc((int)sizeof(double)); - defines str, then allocates (probably) 8 bytes of memory and assigns its address to str. malloc takes a size_t argument, so the cast (int)sizeof(double) is incorrect. Also, in C the return value of malloc should never be cast. So this line should be char * str = malloc(sizeof(double));
char * str2 = (char *)malloc((int)sizeof(int)); - all the same problems as the preceding line. Should be char *str2 = malloc(sizeof(int));
str = "hello"; - causes a memory leak, because the memory you JUST ALLOCATED two lines earlier is now irretrievably lost. You've got two options here - either don't allocate the memory when defining str or free it first. Let's do the latter:
free(str);
str = "hello";
str2 = "hey jude"; - same problem, similar solution:
free(str2);
str2 = "hey jude";
copyStrings(str2, str); - here you're telling your routine to copy the constant string "hello" over the top of the constant string "hey jude". This will work fine on some systems, but will blow up on other systems. The question is in the treatment of the constant string "hey jude". If it's stored in modifiable memory the code will work just fine. If it's stored in memory which is marked as being unmodifiable, however, it will blow up. It seems that the latter is the case on your system. To fix this you probably want to go back to the previous line and change it to
str2 = malloc(20);
That's more memory than you'll need, but it will work just fine.
free(str); - you're attempting to free the constant string "hello", which is not dynamically allocated memory. This needed to be done prior to the assignment str = "hello";.
free(str2; - same problem as above. This needed to be done prior to the assignment str2 = "hey jude";.
} - correct
Best of luck.

Converting char * to uppercase segfaults

I have a simple program where I have a string I've written in externally (in the case of this snippit, it's user created). And I'm trying to capitalize certain parts of it.
I first strtoked it by a delimiter, and attempted to capitalize it using the toupper function, however I seem to be getting segfaults doing it. Running valgrind provides no error, except simply states that:
Process terminating with default action of signal 11 (SIGSEGV)
==10180== Bad permissions for mapped region at address 0x4007B9
The code:
int main(void) {
char * test;
char * f;
char * s;
char * p;
test = "first:second:third:fourth:";
f = strtok(test,":");
for(p = f; *p; *p = toupper(*p), p++); //segfaults
printf("f is %s \n",f); //this should print "FIRST" as it should be capitalized
return 0;
}
You can't use strtok() on a string literal because it modifies it's argument, and you can't modify a string literal.
Nor can you modify it in this loop
for (p = f; *p; *p = toupper(*p), p++); //segfaults
You need an array or a dynamically allocated block of memory, both of which are writeable, with the array you can initialize using a string literal like this
char array[] = "This is a string literal, you are not allowed to modify it";
/* Now the arest of the code could work but ... */
You also need to check the return value of strtok() which is NULL when it doesn't find what you ask to find.
Using malloc() you can do this too
cosnt char *string_literal = "This is a sample string";
size_t length = strlen(string_literal);
char *buffer = malloc(length + 1);
if (buffer == NULL)
return -1; // Allocation failure.
memcpy(buffer, string_literal, length + 1);
// ^ copy the null terminator too
// Process your newly allocated copy here and,
free(buffer);
NOTE: About your original code with
f = s = p = test = malloc(sizeof(char * ) * 10);
malloc() is not used as a general initialization function, it's used to get a pointer to memory that you can use in the program, you can read/write from/to it. When you ask for memory with malloc() you ask for a specific (usually exact) ammount of bytes to be used in your program.
The returned pointer is then usable if it's not NULL, in case there is an error or the system has ran out of memory it will return NULL.
Your code has a major issue since all the pointers f, s, p and test point to the same memory address and also because you allocated an arbitrary size which might or not be the one you want/need.
When you free(f) and then go on and free(s), you are freeing the same pointer twice and you actually was doing it more than that. Calling free() twice on the same poitner invokes undefined behavior.

Segmentation fault when trying to free memory

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.

Passing strings by value in C

I have two functions, one that creates a pointer to a string and another that manipulates it. I somehow am missing something critical, however:
int foo() {
char * mystring; // Create pointer
bar(&mystring); // Pass in address
printf("%s\n", mystring);
return 0; // There's a reason for this
}
int bar(char ** mystring) {
mystring[0] = malloc(strlen(mystring) + 1); // Since malloc will persist even after exiting bar
*mystring = "hahaha"; // Dereference
return 0;
}
Any enlightenment for my addled brain would be greatly appreciated!
C doesn't have strings as first class values; you need to use strcpy() to assign strings.
strcpy(mystring[0], "hahaha");
In addition to the other answers given, note that:
mystring[0]
is the same as
*(mystring + 0)
which is the same as
*mystring
Your malloc allocates the memory and the pointer is written to mystring but it is overwritten by the next line.
The use of malloc is necessary, but this way:
mystring[0] = malloc(strlen(mystring) + 1);
is wrong, since you can't perform strlen on mystring(because it doesn't contain any string yet and because the pointer itself is not initialized). Allocate buffer with the size of your string. for example:
int bar(char ** mystring) {
char* hello = "hahaha";
*mystring = malloc(strlen(hello) + 1);
strcpy(*mystring, hello);
return 0;
}
BTW, you could use the assignment *mystring = "hahaha"; without the malloc since this is a string stored in the data section, and the data will not be lost after returning from the function, but this way it is read-only data and you cannot modify it. The strcpy is there to copy the string to the allocated buffer.

Resources