zrzut pamięci przy przekazywaniu wartości napisu

0

Witam. Piszę teraz program w C którego zadaniem jest pobranie łańcucha znaków ze spacjami. Następnie zawartość tego łańcucha chcę przesłać do innego. Niestety przy próbie przepisania dostaje komunikat o zrzucie pamięci. Oto kod który napisałem. Czy ktoś miał podobny problem i mógłby poradzić kilkoma wskazówkami?

#include <stdio.h>
#include <stdlib.h>

void  main()
{
	char *komenda = (char *)malloc(sizeof(char) * 100);
	char *historia[20];
	int licznik1=0;
	while (1)
	{
		gets(komenda);

		historia[licznik1]=*komenda;
		licznik1++;
		for(i=0; i<licznik1; i++)
			{
				printf("%s\n",historia[i]);
			}
	}
}
1

Cześć,
Nie używaj gets()! Nie masz wtedy żadnej kontroli nad miejscem w pamięci na przekazywany ciąg - mówię to ogólnie. Nie jest ważne czy to jest tutaj sprawcą błędu czy nie.
Czemu while( 1 ) ??
Co się stanie jak licznik1 będzie większy niż zaalokowane miejsce w pamięci i spróbujesz odczytać nieistniejące miejsce w tabeli historia? Które de facto ma tylko 20 miejsc - to strasznie mało jak na prędkość wykonywania się programu.

edit:
Pozwolę sobie dodać... Nie wiem z jakiego środowiska korzystasz, ale spora część ze znanych mi środowisk ma wbudowany i bardzo przyjazny debugger.
Jest to narzędzie pozwalające przechodzić przez Twój program krok po kroku tak, jakbyś był komputerem wykonującym to co napisał programista. :P Dzięki temu widzisz gdzie w programie jakie wartości i adresy mają zmienne i co się dzieje.
Spróbuj debugować swój program, dzięki temu będziesz mógł szybciej znaleźć odpowiedź i o wieeele więcej się nauczysz widząc jak DOKŁADNIE działa to co napisałeś ;)

0

Program który piszę to własny shell. Pętla while(1) ma za zadanie kontynuować działanie programu dopóki użytkownik nie wyjdzie sam. Wkleiłem część kodu z którą jest problem. Udało mi się poprawić ale pojawił się inny problem z którym na razie sam spróbuję się uporać i w razie problemów będę pytać. Dziękuję za odp :)

Gdy wkleiłem ten program do CodeBlocksa to po kilku zmianach program się skompilował i działał. Korzystałem również z debugera natomiast pisząc w konsoli linuxa nie wiem czy mam taką możliwość ale chyba nie.

0

Ciekawe ;) Własny shell? To wciąż program, który nawet w Linuksie uruchamiasz z poziomu terminala (nawet pisząc w najbardziej surowym Linuksie). Naprawdę musisz pisać w konsoli? Jakiego Linuksa dokładnie używasz?

0

Nie to że piszę w konsoli tylko kompiluje tam :D sam program piszę w zwykłym pliku .c. Mój ubunt to 16.10.

0
  1. co chcesz uzyskać, bo, żeby było poprawnie, to przypisanie powinno wyglądać tak:
historia[licznik1]=komenda;

Jest jednak problem taki, że nie o to Tobie codzi zapewne, chcesz miec pewnie bufor linii w pamięci? jeśłi tak, to powinieneś zrobić to zupełnie inaczej.
Pomijam, już, że lepiej by main zwracało int, by nie używac gets, że jak się allokuje pamięc dynamicznie to należy ją zwolnić, oraz, że tu alokacja jest bez sensu.

0

historia[licznik1]=komenda; w mojej pierwszej wersji również to wyglądało w ten sposób tylko że po wczytaniu kolejnej komendy
nadpisywała mi się cała tablica np. wpisałem ls to do tablicy pod indeksem 0 zostało zapisane ls, gdy wpisałem ls2 to pod indeks 0 i 1 zostało zapisane ls2. Myślałem że pokręciłem właśnie coś ze wskaźnikami ale teraz to już sam nie wiem. Podam jeszcze aktualny kod:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>

void  main()
{
	char komenda[20];                                     //zmienna do której wczytujê komende
	char *historia[20];                                //zmienna w której przechowywuje 20 ostatnich komend
	int licznik1=0;                                    //zmienna s³u¿¹ca do sprawdzania czy mamy 20 ost komend
	FILE *plik;
	plik=fopen("his.txt", "w+b");
	if(!plik)
		printf("BLAD");
	int i;
	while (1)
	{
		gets(komenda);                                  //pobieram komende
		historia[licznik1] = komenda;                    //przekazuje komende do historii
		licznik1++;
		if(licznik1<20)
			for(i=0; i<licznik1; i++)
			{
				fprintf(plik,"%s\n",historia[i]);
			}
		else
			for(i=licznik1-20; i<licznik1; i++)
			{
				fprintf(plik,"%s\n",historia[i]);
			}
	}
	fclose(plik);
}

i właśnie tutaj wydaje mi się że gubię wskaźniki. Do pliku nic się nie zapisuje a na konsoli wypisują się "krzaki".

1

Przecież napisałem, że błąd projektowy masz w char *historia[20]; wcale nie przechowujesz 20 ostatnich komend!!! Nie nadpisuje ci sie wcale cała tablica, tylko nie umiesz wskaźników!

0

Poprawiłem to co mi popdowiedziałeś. Teraz deklaracja wygląda następująco:
char historia = (char) malloc(20sizeof(char));
Problem jest tylko w zapisie do pliku a mianowicie zapisuje się tylko ostatnio dodana komenda. Czy masz jakieś cenne wskazówki co do tego problemu?

0

Nie chcę przechowywać danych w komendzie. Komenda tylko przez przejście pętli ma ścieżkę do pliku ze zmiennymi(potem to parsuje i wykonuje exec). Po każdym przejściu komenda się zmienia i staram się to zapisywać pod kolejnymi indeksami historii.

0

Właśnie w tym jest problem, inaczej bym nie zadawał pytań. Czy zmiana implementacji tablicy historii jest już dobra? Należy szukać problemu w innym miejscu w kodzie?

1 użytkowników online, w tym zalogowanych: 0, gości: 1