[C] Struktury i tablice -> Naruszenie ochrony pamięci

Bash, C, C++, Java, PHP, Ruby, GTK, Qt i wiele innych - wszystko tutaj.
Awatar użytkownika
N.Crash
Piegowaty Guziec
Piegowaty Guziec
Posty: 9
Rejestracja: 31 paź 2006, 12:59
Płeć: Mężczyzna
Wersja Ubuntu: 10.10
Środowisko graficzne: Xfce
Architektura: x86

[C] Struktury i tablice -> Naruszenie ochrony pamięci

Post autor: N.Crash »

Witam.

Mam problem z kodem w C, mianowicie przy uruchomieniu wyskakuje 'Naruszenie ochrony pamięci'.

Mam następującą strukturę:

Kod: Zaznacz cały

struct tstate
	{
	int N;		// dlugosc lancucha
	int n_min;	// liczba zapisanych minimow

	double E;	// energia konformacji
	double min_E;	// minimalna energia osiagnieta przez replike

	int all_steps;	// liczba krokow symulacji
	int n_moves;	// liczba zaakceprowanych ruchow

 	double T; 		// temperatura stanu

	};
I tworzę tablicę takich struktur, w sposób następujący:

Kod: Zaznacz cały

struct tstate **state = malloc( sizeof(struct tstate) * 10);
Następnie, w chwili odwołania do pola (czy jak kolwiek nazywają się zmienne wewnątrz struktur), wyskakuje komunikat: 'Naruszenie ochrony pamięci':

Kod: Zaznacz cały

state[1]->N = 2;
Co ciekawe, powyższa linijka nie wyrzuca takiego komunikatu, gdy zmniejszę liczbę struktur w tablicy, np na 5:

Kod: Zaznacz cały

struct tstate **state = malloc( sizeof(struct tstate) * 5);
Moje pytanie, co zrobić, żebym mógł utworzyć więcej niż te 5 struktur? Szukałem po googlu, ale niestety nic podobnego nie znalazłem.
Awatar użytkownika
Kastagir
Sędziwy Jeż
Sędziwy Jeż
Posty: 89
Rejestracja: 09 sty 2006, 16:36
Płeć: Mężczyzna
Wersja Ubuntu: 17.04
Środowisko graficzne: Inne
Architektura: x86_64

Odp: [C] Struktury i tablice -> Naruszenie ochrony pamięci

Post autor: Kastagir »

W tym miejscu tworzysz tablicę tablic (bo używasz dwóch * ):

Kod: Zaznacz cały

struct tstate **state = malloc( sizeof(struct tstate) * 10);
Identyfikator tablicy jest wskaźnikiem więc, stworzenie tablicy (jednowymiarowej, 10 elementowej, indeksowanej od 0 do 9) twoich struktur wygląda tak:

Kod: Zaznacz cały

struct tstate *state = malloc( sizeof(struct tstate) * 10);
a potem odwołujesz się do poszczególnych składników:

Kod: Zaznacz cały

state[1].N = 2;
"Search you should use, my young padawan"
kklimonda
Zakręcona Traszka
Zakręcona Traszka
Posty: 585
Rejestracja: 20 kwie 2008, 04:21
Płeć: Mężczyzna
Wersja Ubuntu: 11.04
Środowisko graficzne: GNOME

Odp: [C] Struktury i tablice -> Naruszenie ochrony pamięci

Post autor: kklimonda »

Teoretycznie coś takiego działa: http://pastebin.com/f271f417d - ale ja już teraz na czuja w C piszę, za dawno nie ruszałem języka.
Awatar użytkownika
N.Crash
Piegowaty Guziec
Piegowaty Guziec
Posty: 9
Rejestracja: 31 paź 2006, 12:59
Płeć: Mężczyzna
Wersja Ubuntu: 10.10
Środowisko graficzne: Xfce
Architektura: x86

Odp: [C] Struktury i tablice -> Naruszenie ochrony pamięci

Post autor: N.Crash »

Dzięki za szybką odpowiedź, ale...

Niestety potrzebuję tworzyć tablicę przez 2 '**', bo dalej mam funkcję przyjmującą jako parametr wskaźnik do tstate:

Kod: Zaznacz cały

void save_state(t_state *state);
Którą chcę wywoływać po kolei dla każdego tstate, a więc iterując po i:

Kod: Zaznacz cały

save_state( state[i]);
bo następnie w ciele tej funkcji (i wielu innych również) odwołuje się do state->N.

w przypadku z jednym znakiem '*' powyższe wywołanie nie zadziała, z 2 znakami '**' jest już dobrze, ale wyskakuje naruszenie ochrony pamięci.
Awatar użytkownika
Hauleth
Wytworny Kaczor
Wytworny Kaczor
Posty: 382
Rejestracja: 18 sie 2008, 17:43
Płeć: Mężczyzna
Wersja Ubuntu: inny OS
Środowisko graficzne: GNOME
Architektura: x86

Odp: [C] Struktury i tablice -> Naruszenie ochrony pamięci

Post autor: Hauleth »

Kod: Zaznacz cały

save_state( &state[i]);
A tak nie pójdzie??
Jeśli problem rozwiązany dodaj na początku tematu [SOLVED].

Biblioteka do C++ - Bust Lib: http://code.google.com/p/bust/
Awatar użytkownika
N.Crash
Piegowaty Guziec
Piegowaty Guziec
Posty: 9
Rejestracja: 31 paź 2006, 12:59
Płeć: Mężczyzna
Wersja Ubuntu: 10.10
Środowisko graficzne: Xfce
Architektura: x86

Odp: [C] Struktury i tablice -> Naruszenie ochrony pamięci

Post autor: N.Crash »

Hauleth pisze:

Kod: Zaznacz cały

save_state( &state[i]);
A tak nie pójdzie??
W tym wypadku już się kompiluje, ale wtedy ta linijka zwraca naruszenie ochrony pamięci (już dla 2-elementowej tablicy).
kklimonda
Zakręcona Traszka
Zakręcona Traszka
Posty: 585
Rejestracja: 20 kwie 2008, 04:21
Płeć: Mężczyzna
Wersja Ubuntu: 11.04
Środowisko graficzne: GNOME

Odp: [C] Struktury i tablice -> Naruszenie ochrony pamięci

Post autor: kklimonda »

No to gdb w dłoń i debuguj - powinno działać.
arrevalk
Piegowaty Guziec
Piegowaty Guziec
Posty: 29
Rejestracja: 07 sie 2006, 16:51
Płeć: Mężczyzna
Wersja Ubuntu: 8.10
Środowisko graficzne: GNOME

Odp: [C] Struktury i tablice -> Naruszenie ochrony pamięci

Post autor: arrevalk »

Nie wiem czy to literówka ale deklarujesz strukture tstate tak:

Kod: Zaznacz cały

struct tstate{...};
a w kodzie uzywasz jej tak:

Kod: Zaznacz cały

save_state(t_state *state)
Jeżeli t_state to typedef to ok ale jezeli nie to deklaracja funkcji moim zdaniem powinna wyglądać tak:

Kod: Zaznacz cały

save_state(struct tstate *state)
Awatar użytkownika
Hauleth
Wytworny Kaczor
Wytworny Kaczor
Posty: 382
Rejestracja: 18 sie 2008, 17:43
Płeć: Mężczyzna
Wersja Ubuntu: inny OS
Środowisko graficzne: GNOME
Architektura: x86

Odp: [C] Struktury i tablice -> Naruszenie ochrony pamięci

Post autor: Hauleth »

Jeśli to ANSI C. Bo w C++ to już nie trzeba, ale raczej C skoro się bawi mallocem :D
Jeśli problem rozwiązany dodaj na początku tematu [SOLVED].

Biblioteka do C++ - Bust Lib: http://code.google.com/p/bust/
arrevalk
Piegowaty Guziec
Piegowaty Guziec
Posty: 29
Rejestracja: 07 sie 2006, 16:51
Płeć: Mężczyzna
Wersja Ubuntu: 8.10
Środowisko graficzne: GNOME

Odp: [C] Struktury i tablice -> Naruszenie ochrony pamięci

Post autor: arrevalk »

@N.Crash
A czy możesz pokazać kod funkcji save_state()? Bo wg twojego ostatniego posta, to właśnie ta funkcja powoduje błąd.
Edit:
U mnie taki kod działa bez problemowo:

Kod: Zaznacz cały

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

struct testowa_struktura{
    int pole1;
    int pole2;
};

void save_state(struct testowa_struktura *dane){
    printf("Pole1: %d\n", dane->pole1);
    printf("Pole2: %d\n", dane->pole2);
};


int main(int argc, char** argv) {
    struct testowa_struktura *tablica_struktur;
    tablica_struktur = malloc(sizeof(struct testowa_struktura) * 1000);
    tablica_struktur[999].pole1 = 200;
    tablica_struktur[999].pole2 = -300;
    save_state(&(tablica_struktur[999]));
    return (EXIT_SUCCESS);
}
Awatar użytkownika
N.Crash
Piegowaty Guziec
Piegowaty Guziec
Posty: 9
Rejestracja: 31 paź 2006, 12:59
Płeć: Mężczyzna
Wersja Ubuntu: 10.10
Środowisko graficzne: Xfce
Architektura: x86

Odp: [C] Struktury i tablice -> Naruszenie ochrony pamięci

Post autor: N.Crash »

@arrevalk
Tak się składa, że funkcja save_state nie robi nic innego, jak fprintfem zapisuje do pliku, odnosząc się do pól poprzez strzałkę '->'. Wszystko działa dobrze, gdy tworzę 1 strukturę, a cyrk z naruszeniem ochrony pamięci zaczyna się przy tablicy conajmniej dwuelementowej.

Pokombinowałem trochę i znalazłem rozwiązanie mało optymalne i eleganckie (idąc w myśl zasady: czas programisty jest cenniejszy niż czas komputera), ale działające:
Z racji iż struktur nie będzie raczej więcej niż 20, na sztywno robię tablicę dwudziestoelementową i najwyżej nie będę wykorzystywał wszystkich elementów:

Kod: Zaznacz cały

tstate *states[20];
	
	for(int i=0; i<20; i++)
	{
		states[i] = malloc(sizeof(tstate));
	}
	
	states[2]->N = 9;
	
	printf("%d \n", states[2]->N);
	
	save_state( states[1]);
Dzięki wszystkim za odpowiedzi. Jeżeli będziecie mieć sugestie na bardziej eleganckie rozwiązania, chętnie je przetestuję.
arrevalk
Piegowaty Guziec
Piegowaty Guziec
Posty: 29
Rejestracja: 07 sie 2006, 16:51
Płeć: Mężczyzna
Wersja Ubuntu: 8.10
Środowisko graficzne: GNOME

Odp: [C] Struktury i tablice -> Naruszenie ochrony pamięci

Post autor: arrevalk »

Strasznie się uparłeś na podwójny wskaźnik, jeżeli tak bardzo nie chcesz przekazywać adresu zmiennej do funkcji a wolisz bezpośrednio wskaźnik to na podstawie mojego poprzedniego przykładu można zrobić to jeszcze tak:

Kod: Zaznacz cały

save_state(tablica_struktur+i);
Gdzie i to po prostu i-ty element tablicy.
ODPOWIEDZ

Wróć do „Programowanie”

Kto jest online

Użytkownicy przeglądający to forum: Obecnie na forum nie ma żadnego zarejestrowanego użytkownika i 3 gości