printing fields of structure in c (dynamic memory allocation) - c

I'm a noob at C and create this program to help me learn. Purpose is to add soccer players to a team and print info.
I'm trying to print fields of my club structure but when my program gets to my print method, all my values are garbage or addresses. How can I get "real" values
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 8
typedef struct player {
int id;
char *position;
} Player;
typedef struct club {
int size;
Player *team[SIZE];
} Club;
Player *create_player(int id, const char *description);
void create_team(Club *club);
void print_club(const Club *club);
void add_player_to_club(Club *club, int id, const char *position);
int main() {
Club club;
create_team(&club);
add_player_to_club(&club, 1, "forward");
add_player_to_club(&club, 2, "goalie");
print_club(&club);
return 0;
}
Player *create_player(int id, const char *description){
Player *player;
player = malloc(sizeof(Player));
if(description == NULL){
player->position = NULL;
} else {
player->position = malloc(strlen(description) + 1);
strcpy(player->position, description);
player->id = id;
}
return player;
}
void create_team(Club *team){
team = malloc(sizeof(Club));
if (team == NULL) {
return;
} else {
team->size = 0;
}
}
void print_club(const Club *club) {
int i = 0;
if (club == NULL) {
return;
} else if (club->size == 0) {
printf("No team members\n");
} else {
for (i = 0; i < SIZE; i++) {
printf("Id: %d Position: %s\n", club->team[i]->id,
club->team[i]->position);
}
}
}
void add_player_to_club(Club *club, int id, const char *position){
if (club == NULL || club->size >= SIZE) {
return;
} else {
Player player = *create_player(id, position);
club->team[club->size -1] = &player;
}
}
Here's a pic of my debugging session
Debugger

Problem 1
create_team is not doing anything useful for main. You are changing the value of a function local variable. As a consequence club remains uninitialized in main. You proceed to use it as though it is valid object, which is cause for undefined behavior.
You can change that function to:
void create_team(Club *team){
team->size = 0;
for (int i = 0; i < SIZE; ++i )
{
team->team[i] = NULL; // Unfortunate choice of variable names
// but should be OK.
}
}
Problem 2
You are storing a pointer to a function local variable in add_player_to_club. That pointer becomes invalid the function returns.
Player player = *create_player(id, position);
club->team[club->size -1] = &player; // Problem
Change it to:
club->team[club->size] = create_player(id, position);
club->size++;
Problem 3
You are printing too may Players in print_club. There aren't always SIZE number of Players in the team. Change the line
for (i = 0; i < SIZE; i++) {
to
for (i = 0; i < club->size; i++) {

Related

realloc fails in simple dict library

I wrote a lightweight dictionary for a quick project with C, and I am getting the error: realloc(): invalid next size. I know this means my heap is corrupted somehow, but I'm not sure what I did wrong, it seems like my code is super simple.
The realloc always fails the fourth access, ie when dict->num_kvs = 4
Below is my code. It includes the dict library as well as the function that is using it. Any help would be much appreciated
Offending function:
int* get_letter_frequencies(char* stream) {
Dict* dict = Dict_initialize();
for(int i = 0; i < strlen(stream); i++) {
Dict_increment_or_add_key(dict, stream[i]);
}
int* to_return = Dict_get_values_array(dict);
Dict_free();
return to_return;
}
simple_dict.c (plus the struct definitions)
typedef struct kv_pair {
char key;
int value;
} KV_Pair;
typedef struct dict_ {
struct kv_pair* kv_pairs;
int num_kvs;
} Dict;
Dict* Dict_initialize() {
Dict* to_return = malloc(sizeof(Dict));
to_return->num_kvs = 0;
to_return->kv_pairs = NULL;
return to_return;
}
void Dict_free(Dict* dict) {
free(dict->kv_pairs);
free(dict);
}
int Dict_add_key(Dict* dict, char key) {
dict->num_kvs++;
printf("next size: %d\n", dict->num_kvs);
dict->kv_pairs = realloc(dict->kv_pairs, dict->num_kvs * sizeof(KV_Pair));
printf("realloc passed \n");
dict->kv_pairs[dict->num_kvs].value = 1;
return 0;
}
int Dict_find_key(Dict* dict, char key){
for(int i = 0; i < dict->num_kvs; i++) {
char cur_key = dict->kv_pairs[i].key;
if(cur_key == key) {
return i;
}
}
return -1;
}
int Dict_increment_or_add_key(Dict* dict, char key) {
int key_index = Dict_find_key(dict, key);
if(key_index == -1) {
Dict_add_key(dict, key);
} else {
dict->kv_pairs[key_index].value++;
}
}
int* Dict_get_values_array (Dict* dict) {
int* to_return = malloc(dict->num_kvs * sizeof(int));
for(int i = 0; i < dict->num_kvs; i++) {
to_return[i] = dict->kv_pairs[i].value;
}
if(dict->num_kvs > 26) {
printf("more than 26 kvs: %d", dict->num_kvs);
}
return to_return;
}
When you try to add the first element, you are incrementing dict->num_kvs to 1, then you allocate a single element. Then this line:
dict->kv_pairs[dict->num_kvs].value = 1;
It will try to write to the [1] element, instead of [0] element. This is out of bounds. You should use:
dict->kv_pairs[dict->num_kvs-1].value = 1;
PS: If you're using GCC or Clang, AddressSanitizer is a great tool to help you detect these type of bugs.

Can't access pointer while navigating linked list

I'm making a simple hash table and a hash function. Each element of the table has a pointer to another node that is used by the insert function when a collision occurs. The problem is that when a collision occurs my code simply crashes when it's navigating the linked list. Here is the code (sorry if it's a little lengthy):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "hash.h"
#define TAM 50
int funcaoHash(int chave, char nome[50]) //Hash function
{
int i;
int hash = chave;
for(i = 0; nome[i] != '\0'; i++)
{
hash = hash + (int)nome[i];
}
hash = hash%TAM;
return hash;
}
void insere(int chave, char nome[50], itemTabela* TabelaHash[TAM]) //Insert function
{
int idx = funcaoHash(chave, nome);
itemTabela* ItemAux = (itemTabela*)malloc(sizeof(itemTabela));
itemTabela* ptrAux = NULL;
ItemAux->chave = chave;
strcpy(ItemAux->nome, nome);
if(TabelaHash[idx] == NULL) //No collision occurred
TabelaHash[idx] = ItemAux;
//If there is a collision
else
{
ptrAux = TabelaHash[idx]->ptr;
//Here the code breaks
while(ptrAux->ptr != NULL)
{
ptrAux = ptrAux->ptr;
}
ptrAux = ItemAux;
}
}
void inicializaTabela(itemTabela* TabelaHash[TAM]) //Initialize tabl
{
int i;
for(i = 0; i < TAM; i++)
TabelaHash[i] = NULL;
}
Here is the node structure:
typedef struct itemTabela
{
char nome[50];
int chave;
struct itemTabela* ptr;
}itemTabela;
And here is the main function:
int main()
{
itemTabela *ptrTabela[TAM] = {};
inicializaTabela(ptrTabela);
insere(6, "Chico", ptrTabela);
insere(6, "Chico", ptrTabela);
return 0;
}
Am I accessing the pointers in the wrong way or doing some ilegal access?
Thanks for your time!
1)
Initialization of ItemAux also requires ptr initialization. like ItemAux->ptr = NULL;
2)
ptrAux = TabelaHash[idx]->ptr;
//Here the code breaks
while(ptrAux->ptr != NULL)
{
ptrAux = ptrAux->ptr;
}
ptrAux = ItemAux;
should be
ptrAux = TabelaHash[idx];
while(ptrAux->ptr != NULL)
{
ptrAux = ptrAux->ptr;
}
ptrAux->ptr = ItemAux;

free memory of struct that has an array of other struct inside - C

I trying to use a dynamic array, when i finish using it, i try to free the memory used and i get this error.
free(): invalid next size (fast): 0x00652098
This are the declarations of the struct variables:
struct player {
int played_time;
int min_time;
int max_time;
int errors;
int color;
};
struct Players {
struct player *array;
size_t player_number;
size_t size;
};
typedef struct Players Player_list;
This are the method used to manage the dynamic array:
void initArray(Player_list *list, size_t initialSize) {
list->array = (struct player *) malloc(initialSize * sizeof(struct player));
list->player_number = 0;
list->size = initialSize;
}
void insertArray(Player_list *list, struct player element) {
if (list->player_number == list->size) {
list->size *= 2;
list->array = (struct player *) realloc(list->array,
list->size * sizeof(struct player));
}
list->array[list->player_number++] = element;
}
void freeArray(Player_list *list) {
free(list->array);
list->array = NULL;
list->player_number = list->size = 0;
}
int disqualified(Player_list *list, int errors) {
int i = 0;
for (i = 0; i < list->player_number; i++) {
if (list->array[i].errors >= errors) {
return 1;
}
}
return 0;
}
And here is how i use it in the main:
/**
* When button is pressed 1 add an error to a random player
*/
void button_s_isr(void) {
int index = rand() % (players.player_number);
point_players->array[index].errors = point_players->array[index].errors + 1;
}
...
int main(void) {
...
// set up of GPIO
// get with scanf NUMBER_OF_PLAYERS and MAX_ERRORS values
int i;
for (i = 0; i < NUMBER_OF_PLAYERS; i++) {
struct player player;
player.color = PLAYER_COLORS[i];
player.errors = 0;
player.max_time = 0;
player.min_time = 0;
player.played_time = 0;
insertArray(&players, player);
}
while (disqualified(&players, MAX_ERRORS) != 1) {
// wait
}
printf("\n Se ha acabdo el juego: ");
freeArray(point_players);
return EXIT_SUCCESS;
}
I must say i am quite new to C, sorry if it is difficult to understand.
What i want to do is a dynamic list of struct (players), where each player has own parameters (played_time, min_time , max_time, errors, color). And inside the main i want to have a game where i can control this parameters from each player.
Any help to improve the code is appreciated.
the posted code:
does not compile
is missing definitions for PLAYER_COLORS[i], which is a bad idea to use as the number of players could exceed the available colours in the array.
incorrectly calculates the size needed for the realloc()
fails to check the returned values from functions like malloc() and realloc()
contains a confusing (even for the OP) naming of variables and struct instances
is missing the definition for num_jugadores
incorrectly tries to assign a struct rather than copying the struct
fails to declare an instance of struct Players
and now, corrected code that compiles cleanly:
caveat: not fully tested
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // memcpy()
struct player
{
int played_time;
int min_time;
int max_time;
int errors;
int color;
};
struct Players
{
struct player *array;
size_t player_number;
size_t numPlayers;
};
//This are the method used to manage the dynamic array:
void freeArray(struct Players *pArray)
{
free(pArray->array);
pArray->array = NULL;
pArray->player_number = pArray->numPlayers = 0;
}
void initArray( struct Players *pArray )
{
if( NULL == (pArray->array = malloc(sizeof(struct player)) ) )
{ // then malloc failed
freeArray( pArray );
exit( EXIT_FAILURE );
}
// implied else, malloc successful
pArray->player_number = 0;
pArray->numPlayers = 1;
}
size_t sizeof_array(size_t size)
{
return size * sizeof(struct player);
}
void insertArray(struct Players *pArray, struct player *element)
{
if (pArray->player_number == pArray->numPlayers)
{ // then currently allocated memory for array of players is full
struct player *temp = NULL;
if( NULL == (temp = realloc(pArray->array, sizeof_array(pArray->numPlayers)*2) ) )
{ // then, realloc failed
freeArray( pArray );
exit( EXIT_FAILURE );
}
// implied else, realloc successful
pArray->numPlayers *= 2;
pArray->array = temp;
}
memcpy( &(pArray->array[pArray->player_number]), element, sizeof( struct player ) );
pArray->player_number++;
}
//and here is how i use it in the main method:
#define num_jugadores (20)
int main( void )
{
int i;
struct Players playerList;
initArray(&playerList);
for (i = 0; i < num_jugadores; i++)
{
struct player myPlayer;
//player.color = PLAYER_COLORS[i];
myPlayer.errors = 0;
myPlayer.max_time = 0;
myPlayer.min_time = 0;
myPlayer.played_time = 0;
insertArray(&playerList, &myPlayer);
}
//...
freeArray(&playerList);
} // end function: main
An error like this usually occurs because you are writing past the end of declared memory. While we could probably find the bug by carefully pouring over every line of code, valgrind would find it much faster for you.
Try compiling your code in debug mode, without optimizations, (gcc -g -O0 if you are using gcc) and run your program under valgrind (e.g., valgrind myprog -my-prog-options). It should flag the error right away.
All this assumes you are running a variant of linux. If you are using visual studio, there will probably be a similar memory checker, but I don't know what it is or how to run it.
Good Luck!

Overlapping and too long integer values in dynamic c structs

I have the following problem.
I need to create a list of savestates with dynamical length. That's why I decided to create a list by defining some structs and connecting dynamically created structs together to build a list of structs which can dynamically be extended and so on.
However, some things seem to not work at all. Here's the relevant code first:
saves.h:
#ifndef SAVES_H
#include<time.h>
#define SAVES_H
#define SVS_STRLEN 500
#define SVS_FILE "savefile.dat"
#define True 1
#define False 0
typedef struct SVS_STATE SVS_STATE;
typedef struct SVS_STATES SVS_STATES;
struct SVS_STATE {
int i_playfield[6][7];
int i_turn;
time_t i_time;
void *next;
};
struct SVS_STATES {
SVS_STATE *states;
int count;
int loaded;
};
void SVS_Add_State(int i_playfield[][7], int i_turn, time_t i_time);
void SVS_Debug_State(SVS_STATE *state);
void SVS_Format_State(SVS_STATE *state, char text[]);
SVS_STATE *SVS_Get_State(int number);
#endif
saves.c:
#include "saves.h"
#include<string.h>
#include<time.h>
SVS_STATE *SVS_Get_State(int number)
{
int i = 1;
SVS_STATE *state;
if (svs_current_state.loaded == False) return NULL;
if (number > svs_current_state.count) return NULL;
state = svs_current_state.states;
printf("printing state 1:");
SVS_Debug_State(state);
while( i < number)
{
i++;
state = (SVS_STATE*)(state->next);
printf("printing state %i:", i);
SVS_Debug_State(state);
}
return state;
}
void SVS_Format_State(SVS_STATE *state, char text[])
{
int i, j;
if (svs_current_state.loaded == False) return;
text[0] = '\0';
strcat(text, "{\0");
for (i = 0; i < X_SIZE; i++)
{
strcat(text, "{\0");
for(j = 0; j < Y_SIZE; j++)
{
strcat(text, "%i,\0");
sprintf(text, text, state->i_playfield[i][j]);
}
strcat(text, "}\0");
}
strcat(text, "};%i;%i\n\0");
sprintf(text, text, state->i_turn, state->i_time);
printf("\nFormatted state:%s\n", text);
}
void SVS_Debug_State(SVS_STATE *state)
{
char text[SVS_STRLEN];
SVS_Format_State(state, text);
printf("%s\n", text);
}
void SVS_Add_State(int i_playfield[][7], int i_turn, time_t i_time)
{
int i, j;
SVS_STATE *laststate, *newstate;
newstate = (SVS_STATE*)malloc(sizeof(SVS_STATE));
printf("adding state with time:%i\n", i_time);
if (svs_current_state.loaded == False) return;
for (i = 0; i < 6; i++)
for (j = 0; j < 7; j++)
newstate->i_playfield[i][j] = i_playfield[i][j];
newstate->i_turn = i_turn;
newstate->i_time = i_time;
newstate->next = NULL;
printf("initialized state:");
SVS_Debug_State(newstate);
if (svs_current_state.coun > 0)
{
laststate = SVS_Get_State(svs_current_state.count);
laststate->next = (void*)newstate;
} else
svs_current_state.states=newstate;
svs_current_state.count++;
}
int main()
{
int i_playfield[6][7] = {0};
// mark saves library as loaded here, but removed function, since it
// just sets svs_current_state.loaded (which is the global struct of
// type SVS_STATES) to 1
SVS_Add_State(i_playfield, 1, time(NULL));
i_playfield[0][0] = 2;
SVS_Add_State(i_playfield, 2, time(NULL));
return 0;
}
The actual problems I encountered while using the printf's and Debug_State calls in these functions:
- the i_time I give is printed out once in Add_State(), correctly. Means it is a legal time and stuff, but when printed out after creating the full state by using Format_State() the string is 50 percent to long and the last part is displayed twice, for example:
if the time is 12345678, it is displayed correctly while debugging in Add_State, but Format_State() displays 123456785678.
- second problem: the first state added works, more or less, fine. But after adding a second one, printing the first state (retrieved by using Get_State and formatted with Format_State) prints a mixture of two states, for example something like this:
state 1: {{0,0,0,0,0,0,0}{0,0,0,0,0,0,0}{0,0,0,0,0,0,0}...
{0,0,0,0,0,0}};1;123456785678
state 2: {{0,0,0,0,0,0}{0,0,0,0,0,0}...
{0,0,0,0,0,0}};2;1234567856785678,0}{0,0,0,0,0,0}...
Thanks for reading.
These calls
sprintf(text, text, ...
invoke undefined behaviour, as the target buffer and one of the other arguments overlap.
From the POSIX specs to sprintf():
If copying takes place between objects that overlap as a result of a call to sprintf() [...], the results are undefined.

C Programming Copy Substring

Im trying to copy substrings from one char* to another, when I printf(%c) it shows the chars printing, but at end of add method, i use printf(%s) to print entire string and nothing is printing out. Any help is appreciated - also perhaps a better method for substrings in C than char by char?
Code below:
int aliasCount;
typedef struct Alias {
char* alias;
char* actual;
struct Alias* next;
}Alias;
Alias* aliasHead;
void addAlias(char* new);
addAlias method
void addAlias(char* new)
{
strip(new);
Alias* newAlias = (Alias*)malloc(sizeof(Alias));
//Get start-end position for alias
int start=0; int end=0; int countSpace=0;
for(int i = 0; i < strlen(new); i++)
{
//Check for space
if(new[i]==' ')
{
printf("found space %d\n",i);
countSpace++;
if(countSpace==1)
{
start=i;
}
else if(countSpace==2)
{
end=i;
break;
}
}
}
//malloc memory
newAlias->next=NULL;
newAlias->alias=(char*)malloc(sizeof(char)*(end-start));
newAlias->actual=(char*)malloc(sizeof(char)*(strlen(new)-end+1));
//Get substring,
//Copy char by char from alias to node
for(int i = 0; i < strlen(new); i++)
{
if(i>start && i<end) //Alias
{
newAlias->alias[i] = new[i];printf("'%c'",newAlias->alias[i]);
}
else if(i>end) //Actual command
{
newAlias->actual[i] = new[i];printf("'%c'",new[i]);
}
}
printf("%s\n%s\n",newAlias->alias,newAlias->actual);
if(aliasCount==0)
{
aliasHead = newAlias;
}
else
{
Alias* curr = aliasHead;
for(int i = 0; i < aliasCount; i++)
{
curr=curr->next;
}
curr->next = newAlias;
}
aliasCount++;
printf("%s\n%s\n",aliasHead->alias,aliasHead->actual);
}
Your indices are wrong; you copy the range from new[start+1] to new[end-1] into the range from alias[start+1] to alias[end-1], when you actually need to copy it into the range from alias[0] to alias[end-start-2]:
newAlias->alias[i-start-1] = new[i];printf("'%c'",newAlias->alias[i]);
and similarly (mutatis mutandis) for actual.

Resources