Okay, zuerst einmal, faire Warnung, das ist ein Projekt für eine Klasse. Ich suche keine andere Hilfe als mein Speicherleck zu reparieren. Ich stelle mir vor, dass ich einige schreckliche Kodierungspraktiken über den Raum dieses C-Codes verfolgt habe. Egal, wenn ich Valgrind nach der Ursache der Speicherlecks suche, ist mir überhaupt nicht klar, welche Speicherlecks mir fehlen. Ich weiß, dass es mindestens zwei Strings gibt, die ich nicht freigebe, sondern dass ich malloc() ed, basierend auf der Größe der valgrind-Ausgabe. Da ich einen Teil des überflüssigen Codes aus dem Projekt herausgenommen habe, sind die Valgrind-Zeilennummern möglicherweise sehr schlecht, deshalb habe ich sie mit Kommentaren versehen, um Ihnen das zu erleichtern.Hausaufgaben: Ich habe irgendwo ein Speicherleck, aber ich kann es nicht finden. Irgendwelche Tipps, wie man Valgrind effektiver nutzen kann?
Ein wenig Hintergrund, ich bin die grundlegenden Funktionen eines Shell zu schreiben. Es unterstützt derzeit die folgenden:
1.Take Benutzereingabe
2.Parse der Eingabe in ein CmdIn struct
3.Execute der Befehl, vorausgesetzt, es ist nicht ein Rohr in ihr hat.
4.free den Raum von dem CmdIn ich erstellt, und von vorn beginnt bei Schritt 1 Dies ist, wo das Problem auftritt.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#define MAX_SIZE 1024
#define MAX_CLEN 2097152
#define READ_END 0
#define WRITE_END 1
#define CHILD_STATUS 0
struct cmdin
{
char *cmd;
char **args;
int nargs;
int pipeflag;
};
//check if the last argument of the command passed to it is a pipe.
//if so, return the position of the pipe, otherwise, return 0
//if it has already found a pipe, it will return the position of that pipe
int conpipe(struct cmdin * cmd)
{
if(!cmd->pipeflag)
{
if(!strcmp(cmd->args[cmd->nargs], "|"))
{
return cmd->nargs;
}
else
{
return 0;
/* PROBLEM LINE BELOW */
} // line 46, where valgrind claims one of the problems exists
}
else
{
//printf("pipeflag: %d\n", cmd->pipeflag);
return (cmd->pipeflag);
}
}
//free the command after each runthrough
int freeze(struct cmdin cmd)
{
int i;
for(i=0; i <= (cmd.nargs); i++)
{
//printf("cmd.args[%d]: %s\n",i, cmd.args[i]);
/* PROBLEM LINE BELOW*/
free(cmd.args[i]); //this is line 62, as noted by valgrind
}
free(cmd.args);
free(cmd.cmd);
return 0;
}
//parse input, and add a null to the end
struct cmdin * parse(char *cmd)
{
//allocate space for the command
struct cmdin *ped = malloc(sizeof(struct cmdin));
//declare pipeflag, and nargs as 0
ped->pipeflag = 0;
ped->nargs = 0;
//allocate space for the array of strings, and for the string cmd.
ped->args = malloc(sizeof(char*) * MAX_SIZE);
ped->cmd = malloc(sizeof(char) * MAX_SIZE);
//scan the input, and put the first argument into the cmd string
sscanf(cmd, "%s %[^\n]", ped->cmd, cmd);
//allocate space for the next string, and then copy cmd to it.
ped->args[ped->nargs] = malloc(sizeof(char) * MAX_SIZE);
strcpy(ped->args[ped->nargs], ped->cmd);
ped->pipeflag = conpipe(ped);
/* PROBLEM LINE BELOW*/
ped->nargs++; // line 86, where valgrind claims the second leak is called?
ped->args[ped->nargs] = malloc(sizeof(char) * MAX_SIZE);
//loop that allocates space for a command, and then assigns
//the next arg to it.
while(sscanf(cmd, " %s %[^\n]", ped->args[ped->nargs], cmd) == 2)
{
ped->pipeflag = conpipe(ped);
ped->nargs++;
ped->args[ped->nargs] = malloc(sizeof(char) * MAX_SIZE);
}
strncpy(ped->args[ped->nargs], cmd, strlen(cmd)-1);
ped->nargs++;
//ped->args[ped->nargs] = malloc(sizeof(char) * MAX_SIZE);
ped->args[ped->nargs] = NULL;
return ped;
}
int main()
{
char cwd[MAX_CLEN];
getcwd(cwd, sizeof(cwd));
char input[MAX_CLEN];
char *exit = "exit\n";
char *cd = "cd";
//Command to take input
printf("tosh$ ");
fgets(input, sizeof input, stdin);
while(strcmp(input, exit))
{
//Command to parse input
struct cmdin *cmd;
cmd = parse(input);
//if there is not a pipeflag
if(!cmd->pipeflag)
{
//Change directories
if(!strcmp(cd, cmd->args[0]))
{
chdir(cmd->args[1]);
getcwd(cwd, sizeof(cwd));
}
else if(strcmp(input, exit))
{
//command to run input
int child_pid;
child_pid = fork();
if(child_pid == 0)
{
if(strcmp(cmd->args[1],cmd->args[0]))
{
execvp(cmd->cmd, cmd->args);
}
else
{
free(cmd->args[1]);
cmd->args[1] = NULL;
cmd->nargs--;
execvp(cmd->cmd, cmd->args);
}
}
else
{
wait(&child_pid);
}
}
freeze(*cmd);
free(cmd);
}
//Command to take input
printf("tosh$ ");
fgets(input, sizeof input, stdin);
}
return 0;
}
Hinweis: Die Eingabe für diesen valgrind, sah wie folgt aus:
tosh$ ls -al
tosh$ exit
Die valgrind Heap und Leak Zusammenfassungen, sind wie folgt:
HEAP SUMMARY:
==4901== in use at exit: 4,096 bytes in 2 blocks
==4901== total heap usage: 6 allocs, 4 frees, 24,600 bytes allocated
==4901==
==4901== 2,048 bytes in 1 blocks are definitely lost in loss record 1 of 2
==4901== at 0x4C2B3F8: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4901== by 0x400A48: parse (tosh.c:46)
==4901== by 0x400C97: main (tosh.c:86)
==4901==
==4901== 2,048 bytes in 1 blocks are definitely lost in loss record 2 of 2
==4901== at 0x4C2B3F8: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4901== by 0x400BDE: parse (tosh.c:62)
==4901== by 0x400C97: main (tosh.c:86)
==4901==
==4901== LEAK SUMMARY:
==4901== definitely lost: 4,096 bytes in 2 blocks
==4901== indirectly lost: 0 bytes in 0 blocks
==4901== possibly lost: 0 bytes in 0 blocks
==4901== still reachable: 0 bytes in 0 blocks
==4901== suppressed: 0 bytes in 0 blocks
UPDATE: Wie pro Antrag . Mein Makefile:
CC=gcc
CFLAGS=-g -Wall
TARGET=tosh
$(TARGET): $(TARGET).c
$(CC) $(CFLAGS) -o $(TARGET) $(TARGET).c
Valgrind Version: valgrind-3.7.0
gcc Version: gcc (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2
echo $ LD_PRELOAD:
(Diese gedruckte nichts)
'Alle Haufen Blöcke befreit wurden - keine Lecks sind möglich'. Sie haben jedoch Ihren Speicher nur freigegeben, wenn '! Cmd-> pipeflag' ist und Sie eine Menge falscher Lese-/Schreibvorgänge im Speicher haben (valgrind memcheck listet sie alle auf) – keltar
@keltar Ist nicht der 'LECK SUMMARY: definitiv verloren: 4096 Bytes in 2 Blöcken' Sagen, dass ich Gedächtnis verloren habe? –
Ja. Aber mit dem von Ihnen bereitgestellten Code meldet er keine Lecks. Sind Sie 100% sicher, dass Sie dieselbe Version ausführen? – keltar