LinuxQuestions.org
Visit Jeremy's Blog.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 04-18-2011, 06:48 PM   #1
C++arl
LQ Newbie
 
Registered: Jun 2009
Posts: 14

Rep: Reputation: 0
Question Why do I get corrupted memory? Error: free(): invalid next size (fast)


Hi all,
I'm writing a toy shell (again ) and this is the code so far:
Code:
/**
	Ett enkelt skal.
	2011-04-16
*/

//includes
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> //För fork
#include <errno.h> //För perror
#include <sys/types.h> //För waitpid
#include <sys/wait.h> //För waitpid
#include <string.h> //För strcat, strdup

//Makron
#define DEBUGLEVEL		1
#define DEBUGT(x)		if(DEBUGLEVEL > 0) printf("%s\n", x)
#define DEBUGN(x)		if(DEBUGLEVEL > 0) printf("%i", x)

int main(int argc, char **argv, char **envp){
	char input[128];
	char *args[7];
	char *c;
	
	while(1){
		
		printf("> ");
	
		//Läs input från användaren, använder fgets för att förhindra buffer overflow.
		fgets(input, 128, stdin);
		//Ta bort '\n', ersätt med '\0' annars hittar inte execv.
		c = strchr(input, '\n');
		*c = '\0';
		
		DEBUGT(input);
	
		if(strcmp(input, "exit") == 0){
			break;
		}
	
		//Skapa ny process.
		pid_t child = fork();

		if(child == 0){
			//Detta är barnet
			
			args[0] = NULL;
				
			//Leta efter programmet i alla mappar i PATH samt i den mapp man befinner sig i nu.
			char *temp = NULL;
			char *path = getenv("PATH");
			
			path = strtok(path, ":");
			while(path != NULL){
				DEBUGT("PATH:");
				DEBUGT(path);
				
				temp = strdup(path);
				
				DEBUGT("TEMP:");
				DEBUGT(temp);
				
				//Klistra ihop sökvägen och sätt parametrar till execv	
				strcat(temp, "/");
				args[0] = strcat(temp, input);
			
				//Sätt övriga parametrar
				args[1] = NULL; //TEMP här
				
				DEBUGT("ARGS[0]:");
				DEBUGT(args[0]);
				
                //run the requested program
				execv(args[0], args);
				
				free(temp);
				path = strtok(NULL, ":");
			}

			//Kommer vi hit så blev det nått fel
			perror("execv");	
			return 1;
		
		}
		else{
			//Jag är föräldern.
		
			//Vänta på att barnet ska bli klart (barnet är en förgrundprocess), och kolla dess status.
			int childStatus;
			waitpid(child, &childStatus, 0);
		
			if(WEXITSTATUS(childStatus) == 0){
				DEBUGT("Child exited normally!");
			}
			else{
				DEBUGT("Child did not exit well!");
			}
		
			//Gör nått. 
		}
	}
	
	return 0;
}
As you can see its in a early stage yet. Now, when I give commands which are less then 4 characters long it works just fine but if I give it commands longer then 3 characters long I get the following error message:
Code:
*** glibc detected *** ./SmallShell: free(): invalid next size (fast): 0x08a1f020 ***
======= Backtrace: =========
/lib/libc.so.6(+0x6c501)[0x803501]
/lib/libc.so.6(+0x6dd70)[0x804d70]
/lib/libc.so.6(cfree+0x6d)[0x807e5d]
./SmallShell[0x8048858]
/lib/libc.so.6(__libc_start_main+0xe7)[0x7adce7]
./SmallShell[0x8048621]
======= Memory map: ========
0025f000-00260000 r-xp 00000000 00:00 0          [vdso]
002e9000-00305000 r-xp 00000000 08:01 651592     /lib/ld-2.12.1.so
00305000-00306000 r--p 0001b000 08:01 651592     /lib/ld-2.12.1.so
00306000-00307000 rw-p 0001c000 08:01 651592     /lib/ld-2.12.1.so
00719000-00733000 r-xp 00000000 08:01 651756     /lib/libgcc_s.so.1
00733000-00734000 r--p 00019000 08:01 651756     /lib/libgcc_s.so.1
00734000-00735000 rw-p 0001a000 08:01 651756     /lib/libgcc_s.so.1
00797000-008ee000 r-xp 00000000 08:01 651618     /lib/libc-2.12.1.so
008ee000-008f0000 r--p 00157000 08:01 651618     /lib/libc-2.12.1.so
008f0000-008f1000 rw-p 00159000 08:01 651618     /lib/libc-2.12.1.so
008f1000-008f4000 rw-p 00000000 00:00 0 
08048000-08049000 r-xp 00000000 08:01 274582     /home/ss/Desktop/ID2206/Labb2/SmallShell
08049000-0804a000 r--p 00000000 08:01 274582     /home/ss/Desktop/ID2206/Labb2/SmallShell
0804a000-0804b000 rw-p 00001000 08:01 274582     /home/ss/Desktop/ID2206/Labb2/SmallShell
08a1f000-08a40000 rw-p 00000000 00:00 0          [heap]
b7600000-b7621000 rw-p 00000000 00:00 0 
b7621000-b7700000 ---p 00000000 00:00 0 
b773a000-b773b000 rw-p 00000000 00:00 0 
b774a000-b774e000 rw-p 00000000 00:00 0 
bfab3000-bfad4000 rw-p 00000000 00:00 0          [stack]
Child exited normally!
And I cant figure out why. I have tested the code with valgrind (I ran the command: valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=20 --track-fds=yes ./SmallShell) and it tells me:
Code:
==2610== All heap blocks were freed -- no leaks are possible
So i dont really know whats going on here. I'm using gcc version 4.4.5 on Ubuntu 10.10. Try it out, give a command shorter than or equal to 3 characters long such as 'pwd' and then a longer one such as 'printenv', see if you guys get the same error. If somebody could shed some light on this it would be greatly appreciated!

//C++arl

Last edited by C++arl; 04-18-2011 at 07:10 PM. Reason: Small error
 
Old 04-18-2011, 10:33 PM   #2
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
I think you are misunderstanding what strcat does (or maybe what strdup does).

strcat does not change the allocation of the destination string. It just copies the source starting in the position replacing the terminating null of the destination.

If the destination buffer isn't big enough, it corrupts memory.

strdup does allocate space for the destination. But only enough to be safe for the size of the source, not enough to use strcat after strdup.

Quote:
free(): invalid next size
Also, you seem to misunderstand the error message you quoted.

When you allocate space (such as with strdup) the a tiny amount of extra space is allocated before and after the chunk you requested and that extra is used for data that is needed when you free your chunk.

Your code overwrote the extra memory allocated right after your chunk. So when you free your chunk, the free() code sees that the data following your chunk (that is needed to free your chunk) is invalid, and issues the error message you quoted.

This is not a memory leak. It is a more serious bug than a memory leak.

Last edited by johnsfine; 04-18-2011 at 10:39 PM.
 
Old 04-19-2011, 07:38 AM   #3
C++arl
LQ Newbie
 
Registered: Jun 2009
Posts: 14

Original Poster
Rep: Reputation: 0
Thank you for your answer!

Yes, comming from java and C++ I unconciously just assumed that all that stuff (allocating more memory for the string etc) would be taken care of by strcat. I changed the code to:
Code:
temp = calloc(strlen(path) + 1 + strlen(input), 1);
strcpy(temp, path);
Which works fine.

Quote:
When you allocate space (such as with strdup) the a tiny amount of extra space is allocated before and after the chunk you requested and that extra is used for data that is needed when you free your chunk.
Just out of curiosity, why is that, what is put in that space, magic number?

//C++arl
 
Old 04-19-2011, 08:22 AM   #4
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
Quote:
Originally Posted by C++arl View Post
why is that, what is put in that space, magic number?
When you free a chunk of memory, free() must figure out whether the physically previous chunk is free and whether the physically following chunk is free. If either of those are free then free() must merge the chunk you just freed with adjacent free chunks.

Various versions of malloc used different data before/after each allocated chunk to help keep track. Starting at either end, it needs to be able to figure out whether a chunk is free and if it is free how big it is. For non free chunks, it needs to be able to figure out how big it is from the beginning, not necessarily from the end.
 
1 members found this post helpful.
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
C++ -- glibc detected *** a.out: free*(): invalid next size (fast): Eikcuhc Programming 2 11-07-2010 02:16 AM
*** glibc detected *** free(): invalid next size (fast): 0x0804a1a8 *** bartonski Programming 1 03-08-2010 02:57 AM
"free(): invalid next size (fast)" C error homer_3 Programming 2 06-01-2009 09:41 AM
grep -Ri <searchterm> * returns glibc detected *** free(): invalid next size (fast) abylin1 Linux - Newbie 3 05-14-2009 04:08 PM
Why i am having free(): invalid next size (normal) error. here is code shrik Linux - Software 0 07-23-2007 04:26 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 11:56 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration