C++ Dynamisch Speicher anlegen für struct

Frank2104

Newbie
Registriert
Nov. 2017
Beiträge
3
Hallo,
ich bekomme es einfach nicht geregelt, die "strcpy" Funktion zu nutzen.
Wir haben einen zusammengesetzten Datentyp

Code:
typedef struct {
char* command;
int count;
} job;

Jetzt gibt es folgende Variable

Code:
char** argv_intern = NULL;

Nach Tastatureingabe wird eine Funktion aufgerufen, welche die Zeichenkette anhand von Leerzeichen zerlegt.
Somit steht in argv_intern jetzt z.B
argv_intern[0] = "ps" ;
argv_intern[1] = "-u" ;

Ich möchte jetzt einfach die getrennten Zeichenketten in ein Struct Objekt kopieren.

Code:
job *newjob;
newjob = (job*) calloc(1, sizeof(job) );
strcpy(newjob->command,argv_intern);

Klappt nicht.
Einzeln kopieren klappt auch nicht.

Code:
strcpy(newjob->command,argv_intern[0]);


-----> Speicherzugriffsfehler (Speicherabzug geschrieben)
Über etwas Hilfe wäre ich sehr dankbar. Ich komme mit den doppelten Pointer nicht klar und weis auch gar nicht, was das sein soll.

Grüße
Frank
 
Ein Speicherzugriffsfehler könnte ein Hinweis darauf sein, dass du einen Pointer dereferenzierst, der auf kein Objekt zeigt.
"newjob->command" könnte daher den Fehler produzieren, soweit der Rückgabewert von "calloc" nicht auf den neu alloziierten Speicher zeigt sondern NULL zurückgegeben hat, sprich "newjob" auf keinen Speicherbereich zeigt. Daher würde ich vor dem newjob->command prüfen ob calloc nicht eventuell NULL zurückgegeben hat statt einen Pointer zum neu alloziierten Objekt.
Darüber hinaus finde ich den Befehl "strcpy(newjob->command,argv_intern)" problematisch, da newjob::command vom Typ char* ist und argv_intern vom Typ char**.
 
Zuletzt bearbeitet:
Ist das C++ (wie im Thema) oder doch C? Das wäre wichtig.

Prinzipiell besteht der Fehler darin, den Zeiger 'command' in der struct nicht vorher explizit mit einem Speicherbereich der Länge des Strings zu initialisieren: command=malloc(...).
 
Du solltest den Speicher für deinen String erstmal allokieren.
 
Grundkurs schrieb:
Darüber hinaus finde ich den Befehl "strcpy(newjob->command,argv_intern)" problematisch, da newjob::command vom Typ char* ist und argv_intern vom Typ char**.

Das ist zwar eine falsche Zuweiseung, muß aber nicht notwendigerweise zu einem Fehler führen. Wenn in command genug Speicher alloziiert wurde, steht halt nur der falsche String drin (der "String", der sich aus der Speicheraddresse ergibt, auf die (char *)argv_intern zufällig zeigt. Höchstwahrscheinlich wird aber der Compiler hier nicht mitspielen.
 
Du must den Speicher für job->command noch allozieren. Das calloc garantiert dir sogar das du da für zunächst für newjob->command einen Nullpointer hast, da du die Adresse des Speicherbereiches des Strings ( nichts anderes ist ein char *)explizit mit Null(en) initialisierts.
Also
newjob = (job*) calloc(1, sizeof(job) );
/* Check auf Nullpointer weggelassen */
newjob->command = calloc(1, strlen(argv[0]+1))
/* Check auf Nullpointer weggelassen */
Und du kannst auch nicht alle Argumente in einem Rutsch mit strcpy kopieren, da strcpy nur bis zum ersten Nullzeichen ( das den ersten String terminiert) kopiert.
 
Solltest du die STL libary zur Verfügung haben würde ich dir raten mit STL Containern zu arbeiten. Das ganze Pointer gedöns führt nur zu bugs. Du kannst einfach eine Vector von strings in das struct packen und da addest du dann die ausgelesenen Daten.

Wenn pointer dann SmartPointer welche wiederum in der STL library zur Verfügung stehen.
 
herliTz_234 schrieb:
Solltest du die STL libary zur Verfügung haben würde ich dir raten mit STL Containern zu arbeiten. Das ganze Pointer gedöns führt nur zu bugs.
Hmmm, wenn das verstanden und richtig dokumentiert wird, führt das nicht notwendigerweise zu Bugs. Wenn man Zeiger aber nicht versteht, führt das sicherlich fast immer zu Bugs. Allerdings sollte man, wenn man Zeiger nicht kann, nur sehr vorsichtig mit Sprachen wie C oder auch C++ arbeiten, da es unwahrscheinlich ist, daß man "nur Zeiger" nicht verstanden hat. Auch STL (oder hier: std::string) lösen nicht alle Probleme von selber.
 
Wenn man C++ programmieren will, sollte man die Mittel der Sprache auch nutzen, also z.B. die STL benutzen.
Oder aber man sollte konsequent in C programmieren und die da vorhandenen Mittel benutzen.
Nicht aber den C++ Compiler als C-Compiler missbrauchen.
 
Hallo zusammen, schonmal vielen Dank für Eure Hilfe.
Jetzt kann ich die Zeichenketten aneinanderfügen, habe aber das problem, dass ich mit "strcpy"
wieder die Fehlermeldung "Speicherzugriffsfehler" bekomme.

Code:
job *newjob;
newjob = (job*) calloc(1, sizeof(job) );
int stringlen = 20

newjob->command = (char*) malloc(stringlen * sizeof(char) );
if(newjob->command == NULL)
  {
   printf("Speicheranforderung fehlgeschlagen");
  }

char buffer[stringlen];

for(int i = 0; i< stringlen; i++)
  {
   buffer[i] = '\0';
   newjob->command[i] = '\0';
  }

for(int i = 0; i < numtokens ; i++)
  {
  strcat(buffer, argv_intern[i];
  strcat(buffer , " ");
  }

printf("\n%s\n", buffer);
strcpy(newjob->command , buffer);
printf("\n%s\n",newjob-command);

Beide Zeichenketten ( buffer , newjob->command) werden ausgegeben, aber
die vorletzte Anweisung "strcpy" generiert wieder den Fehler bei Unix
"Speicherzugriffsfehler (Speicherabzug geschrieben)"
 
Frank2104 schrieb:
Code:
...
printf("\n%s\n", buffer);
strcpy(newjob->command , buffer);
printf("\n%s\n",newjob-command);
die vorletzte Anweisung "strcpy" generiert wieder den Fehler bei Unix
"Speicherzugriffsfehler (Speicherabzug geschrieben)"

Mach mal bitte aus
Code:
..
printf("\n%s\n", buffer);
ein
Code:
..
printf("\n%s - %d\n", buffer, strlen(buffer));
und sage uns bitte, was dann auf der Konsole steht.
 
und sage uns bitte, was dann auf der Konsole steht.

Jap gemacht.
Also man erhält als Ausgabe folgendes:


job ./endless - 14

Mit Nullterminierung müsste das ja stimmen und in newjob->command ist Platz für 20 Zeichen.
 

Anhänge

  • 11.jpg
    11.jpg
    46 KB · Aufrufe: 273
Frank2104 schrieb:
Also man erhält als Ausgabe folgendes:job ./endless - 14

Der Fehler muß noch woanders im Programm sein. Irgendwo davor, was wir hier nicht sehen.
 
Warum speicherst du in einem Puffer mit fest vorgegebener Größe zwischen ?
Du kannst dir die benötigte Größe doch vor der Allozierung berechnen. Etwa so :

int buffersize = 0;
for(int i = 0; i < numtokens ; i++)
{
buffersize += strlen(argv_intern) +1 ; // +1: Zusätzlich Platz für je ein Leerzeichen
}
buffersize++ ; // für abschießendes Nullzeichen

Und dann mit calloc(buffersize, sizeof(char))
allozieren und nicht mit malloc(buffersize * sizeof(char)) wenn du den Speicherbereich mit Nullzeichen initialisiert haben willst.
 
Zurück
Oben