Zum Inhalt springen

Problem bei Programm: Speicherzugriffsfehler


Empfohlene Beiträge

Geschrieben

Guten Morgen,

ich habe schon wieder einen Speicherzugriffsfehler in einem Programm :/

Das Programm soll einen Pfad als Parameter entgegen nehmen, die extension vom restlichen Namen trennen und im restlichen Namen alle Zeichen, die kein alnum sind bzw kein "-" oder "_" sind, durch "_" ersetzen. Kompilieren funktioniert, aber beim Ausführen bekomme ich einen Speicherzugriffsfehler. Ich habe überall printf-Anweisungen eingebaut, weil ich dachte, ich könnte den Fehler eingrenzen, nun weiß ich dadurch zwar wo der Fehler sein soll, aber nicht wo er herkommt ...

Hier erstmal der code:


#include <stdio.h>
#include <dirent.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>

typedef struct content //hier stehen die getrennten zeichenketten
{
char base[64];
char extension[20];
}content;


void split( struct content *c, char *a ) //funktion zum trennen
{
printf("aa");
int i=0, pointpos=0;
int lenght=0;
int l=0, k=0;
lenght=strlen(a);
for(l-=1;l>l-20;l--)
{
printf("a");
if(a[l] == '.')
{
printf("b");
pointpos=l;
while(pointpos<lenght)
{
c->extension[k]=a[l];
k++;
l++;
}
break;
}

}
for(i=0;i<pointpos;i++)
{
c->base[i]=a[i];

}
c->base[i]=0;
}

void kill(char *a)
{
int lenght=0,i=0;
lenght=strlen(a);

for(i=0; i<lenght; i++)
{
if(a[i] == '-' || a[i] == '_' || isalnum(a[i]))
continue;
else
{
a[i]='_';

}
}
}

int main(int number, char *para[5])
{

struct content c;

//int a=0;
//int i =1;
char neu[64];
//int lang=0;

DIR *directory;
struct dirent *entry;
directory = opendir(para[1]);
//struct dirent info;

while((entry=readdir(directory)) != NULL)
{
if(strcmp(entry->d_name,".") != 0 && strcmp(entry->d_name,"..") != 0 )
{
printf("1\n");
split(&c,entry->d_name); //aufteilen des namen in base und extension

printf("2 \n");
kill(c.base); //unzulässige zeichen entfernen

printf("3 \n");
strcpy(neu,c.base); //kopieren der base in neu
printf("4 \n");

strcat(neu,c.extension); //anfügen der extension an neu

printf("5 \n");
if(rename(entry->d_name,neu) == 0)
printf("%s umbenannt in %s \n",entry->d_name,neu);
else
perror("rename");
}
}
return 0;

}


[/PHP]

und das ist die Ausgabe:

[PHP]
# ./rename .
1
Speicherzugriffsfehler

Kann mir jemand sagen, was ich falsch gemacht hab?

Vielen Dank!

Geschrieben

Deine Schleifenvariable l in split läuft von -1 rückwärts. Wenn l kleiner als 0 ist, ist ein Zugriff auf a[l] undefiniert.

Die Schleifenbedingung ist auch kaputt. l>l-20 wird erst dann false, nachdem l den kleinstmöglichen Wert für int erreicht hat.

Geschrieben

Stimmt, das hab ich garnicht gesehen, danke dir! Dass l nicht bei -1 anfangen soll versteh ich (an der Stelle hatte ich lenght erst später hinzugefügt und vergessen es in die Schleife zu nehmen), nur was meinst du mit l>l-20 ? Dass das die einzige Abbruchbedingung ist? Dann würde ich es verstehen, ich hab den Schleifenkopf jetzt geändert:

 for(l=lenght-1;l>l-20 || l!=1;l--)

Aber der Speicherzugriffsfehler ist immernoch da, immerhin wird ja auch nicht "aa" ausgegeben von meiner printf-Anweisung. Also muss doch theoretisch die Übergabe der Variable an split oder die ganze Funktion selbst nicht funktionieren. Oder liege ich da falsch?

Geschrieben
was meinst du mit l>l-20 ?
Für welchen Wert von l soll dieser Ausdruck denn jemals false ergeben?

Die Schleifenbedingung

while(pointpos<lenght)

ist auch nicht gut, wenn man bedenkt, dass sich in der Schleife weder pointpos noch lenght ändert. Damit bleibt auch der Wert dieses Ausdrucks immer gleich. Schöne Endlosschleife.

Aber der Speicherzugriffsfehler ist immernoch da, immerhin wird ja auch nicht "aa" ausgegeben von meiner printf-Anweisung. Also muss doch theoretisch die Übergabe der Variable an split oder die ganze Funktion selbst nicht funktionieren. Oder liege ich da falsch?
Ja, da liegst du falsch. Konsolenausgaben können gepuffert werden. Du könntest fflush(stdout) benutzen, um das Schreiben zu erzwingen. Noch besser wäre natürlich die Verwendung eines Debuggers.
Geschrieben
Ich bin mir jetzt nicht ganz sicher, aber ist entry->d_name nicht ein char-Array?

Also entry ist eine Struktur, die ich selbst definiert habe, vom Typ DIR. Weil ich auf eine Komponente von DIR zugreife, über einen Pointer auf die Komponente d_name zugreife, verwende ich "->".

d_name selbst müsste ein char_array sein...ich hoffe, ich hab jetzt keinen Mist geschrieben ^^``

Für welchen Wert von l soll dieser Ausdruck denn jemals false ergeben?

Also so, wie ich es jetzt nochmal verändert habe, soll es false ergeben, wenn er die letzten 20 Zeichen des Namen abgearbeitet hat (weil ich einfach festlege, dass es keine extension geben wird, die länger als 19 Zeichen ist) oder, wenn l den wert 1 erreicht (beispiel: "backrezept"; a ist das letzte Zeichen, welches überprüft wird, weil der Punkt ja mindestens an 2. Stelle sein muss z.B.: a."out")

Naja, wenn ein Punkt gefunden wird, dann verlasse ich die Schleife einfach mit break, nachdem ich die Position des Punktes gespeichert habe... Es wäre bestimmt sauberer, wenn ich das mit in die Schleifen-Bedingung packe, oder?

Die Schleifenbedingung
while(pointpos<lenght)

ist auch nicht gut, wenn man bedenkt, dass sich in der Schleife weder pointpos noch lenght ändert. Damit bleibt auch der Wert dieses Ausdrucks immer gleich. Schöne Endlosschleife.

Wie Recht du hast...:upps

Ja, da liegst du falsch. Konsolenausgaben können gepuffert werden.

Stimmt ja, nur war mir bisher nie klar, wann das passieren kann. Ist das bei Funktionsaufrufen prinzipiell so, da diese ja ohnehin komplett an die main weitergegeben werden, wenn sie fertig sind?

Geschrieben
Also so, wie ich es jetzt nochmal verändert habe, soll es false ergeben, wenn er die letzten 20 Zeichen des Namen abgearbeitet hat (weil ich einfach festlege, dass es keine extension geben wird, die länger als 19 Zeichen ist) oder, wenn l den wert 1 erreicht
Wenn l gleich 1 ist, steht da

1>(1-20)

also

1>-19

Ist immer noch true.

Eine Zahl ist immer größer als dieselbe Zahl um 20 verringert. Das wird erst dann false, wenn du die Grenze des Wertebereichs erreichst, bei einem 32-Bit-int also jenseits der -2 Milliarden.

Naja, wenn ein Punkt gefunden wird, dann verlasse ich die Schleife einfach mit break, nachdem ich die Position des Punktes gespeichert habe.

.. Es wäre bestimmt sauberer, wenn ich das mit in die Schleifen-Bedingung packe, oder?

Du musst in der Schleifenbedingung einfach dafür sorgen, dass l nicht ungültig werden kann. Und bedenke, dass ein Dateiname keinen Punkt enthalten muss.

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...