Struktury i błąd dostępu do zapisu

0

Witam
piszę program, w którym tworzę następujące struktury:

typedef struct Card
{
	char color;
	int face;
}CardT;

typedef struct Player
{
	char side;
	Card *card;
}PlayerT;

typedef struct Deal
{
	Player *Gracze;
	int PointsNS;
	int PointsEW;
}DealT;

w funkcji main inicjalizuję je poprzez funkcję

void InitStruct(DealT *Rozdanie)
{
	Rozdanie->Gracze = (PlayerT*)malloc(sizeof(PlayerT) * PLAYERS);
	for (int i = 0; i < 4; i++)
	{
		Rozdanie->Gracze[i].side = '\0';
		Rozdanie->Gracze[i].card = (CardT*)malloc(sizeof(CardT) * FACE);
		for (int j = 0; j < 14; j++)
		{
			
			Rozdanie->Gracze[i].card[j].color = 'A'+j;
			Rozdanie->Gracze[i].card[j].face = 1+j;
			printf("%c%d ", Rozdanie->Gracze[i].card[j].color, Rozdanie->Gracze[i].card[j].face);

		}
		printf("\n");
	}
}

Następnie w funkcji, która operuje na tej strukturze próbuję wczytać dane z pliku i przypisać je do odpowiednich pól

void WczytajRozdanie(DealT *Rozdanie)
{
	char temp[3] = { '\0' };
	char linia[LINE_SIZE] = { '\0' };
	FILE *FileT = fopen("C:\\Users\\GONSKABALBINKA\\Desktop\\rozdanie.txt", "r");
	if (Rozdanie == NULL)
	{
		printf("Nie mozna otworzyc pliku\n");
		return;
	}

	while (fgets(linia, LINE_SIZE, FileT) != NULL)
	{
		for(int i=0;i<PLAYERS;i++)
		{
			Rozdanie->Gracze[i].side = linia[0];
			for (int j = 0, len =2 ; j < FACE; j++, len += 3)
			{
				sprintf(temp, "%2s", linia + len);

				Rozdanie->Gracze[i].card[j].color = temp[1]; // W tym miejscu wyrzuca mi wyjątek

Kiedy próbuję przypisać dane do odpowiednich pól otrzymuję komunikat: Zgłoszono nieobsługiwany wyjątek: naruszenie dostępu do odczytu.
Gdzie może być błąd

1

i < 4

vs

i<PLAYERS

trochę mnie martwi. Alokujesz PLAYERS graczy, ale inicjalizujesz tylko 4. Analogicznie dalej w jednym miejscu masz jakieś hardkodowane indeksy, a w drugim jakieś stałe i nie wiadomo czy to te same wartości, a pewnie nie.

3
  1. Zbuduj z -ggdb3 -fsanitize=address.
  2. Podaj prawidłowo przeklejony kod, póki co Twoje struktury się nie skompilują nawet. Generalnie zawężenie problemu do minimum bym się przydało. Jak wołasz InitStruct a potem wczytywanie? Podaj MRE albo chociaż pokaż całość kodu od zawołania InitStruct aż do WczytajRozdanie
  3. Jaki jest LINE_SIZE?
    Poza konkursem raczej:
  4. Nie rzutuj malloca.
0

Poniżej cały kod

#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>


#define LINE_SIZE 41
#define COLOR 4
#define FACE 13
#define PLAYERS 4

#pragma warning(disable : 4996)

typedef struct Card
{
	char color;
	int face;
}CardT;

typedef struct Player
{
	char side;
	Card *card;
}PlayerT;

typedef struct Deal
{
	Player *Gracze;
	int PointsNS;
	int PointsEW;
}DealT;


void WczytajRozdanie(DealT *Rozdanie)
{
	char temp[3] = { '\0' };
	char linia[LINE_SIZE] = { '\0' };
	FILE *FileT = fopen("C:\\Users\\GONSKABALBINKA\\Desktop\\rozdanie.txt", "r");
	if (Rozdanie == NULL)
	{
		printf("Nie mozna otworzyc pliku\n");
		return;
	}


	Rozdanie->Gracze = (PlayerT*)malloc(sizeof(PlayerT) * PLAYERS);
	while (fgets(linia, LINE_SIZE, FileT) != NULL)
	{
		for(int i=0;i<PLAYERS;i++)
		{
			
			Rozdanie->Gracze[i].card = (CardT*)malloc(sizeof(CardT) * FACE);
			Rozdanie->Gracze[i].side = linia[0];
			for (int j = 0, len =2 ; j < FACE; j++, len += 3)
			{
				sprintf(temp, "%2s", linia + len);

				Rozdanie->Gracze[i].card[j].color = temp[1];

				if ((temp[0] >= '0')&&(temp[0] <= '9'))
					Rozdanie->Gracze[i].card[j].face = temp[0] - '0';
				else if (temp[0] == 'T')
					Rozdanie->Gracze[i].card[j].face = 10;
				else if (temp[0] == 'J')
					Rozdanie->Gracze[i].card[j].face = 11;
				else if (temp[0] == 'Q')
					Rozdanie->Gracze[i].card[j].face = 12;
				else if (temp[0] == 'K')
					Rozdanie->Gracze[i].card[j].face = 13;
				else if (temp[0] == 'A')
					Rozdanie->Gracze[i].card[j].face = 14;
			}
		}

		printf("%s", linia);
		printf("\n\n");

	}

}




int main()
{
	DealT *Rozdanie = (DealT*)malloc(sizeof(DealT)*1);
	WczytajRozdanie(Rozdanie);
	


    return 0;
}

To trochę wygląda tak jakbym odwoływał się do miejsca w pamięci, które nie istnieje, ale przecież przydzielam pamięć mallociem

0

To jeszcze dane wejściowe by się przydały do kompletu ale wygląda, że LINE_SIZE przekraczasz.
Dopisz (przed sprintfem)
printf("%d\n", len);
Raz jeszcze: czemu nie chcesz użyć -ggdb3 -fsanitize=address?

EDIT: widzę że to MSVC. Ale nadal w ramach szacunku do czytających wklejaj kompilujący się kod, bo wciąż nie trybi ;P

EDIT2: address sanitizer dla MSVC, proszę bardzo: https://docs.microsoft.com/en-us/cpp/sanitizers/asan?view=msvc-160

2

Zastanów się nad zmianą modelu:

typedef enum { spear,club,diamond,heart; } Color;
typedef enum { f2,f3,f4,f5, ... fJ,fQ,fK,fgA } Face;
typedef struct { Color color; Face face; } Card;
typedef enum { tail,player0,player1,player2,player3,player4,player5,player6; } Where;
typedef struct
{
    Where tale[13*4];
} Tale;
1

Przeanalizuj jak dokładnie działa %2s w printf i co się stanie jak będzie za dużo. LINE_SIZE - nie wiem,może też przekraczasz, ale na pewno nie tylko.

Hint:

Minimum number of characters to be printed. If the value to be printed is shorter than this number, the result is padded with blank spaces. The value is not truncated even if the result is larger.

0
strncat(temp,linia+len,2);
//albo
strncpy(temp, liniat+len,2);

Program debuguje się prawidłowo i wydaje się, że działa
Dzięki za odpowiedzi. Wielkie dzięki

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