Skip to content

PedroZappa/42_get_next_line

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

get_next_line

Because reading a line from a fd is way too tedious. 😪

___

Table o'Contents

About 📌

get_next_line is a 42 Common Core project that delves into how static variables and file descriptors work. It is a challenging introduction to memory allocation.


Implementation 📜

Mandatory Requirements

get_next_line must:

  • Return the contents of a line per function call read from a given file descriptor, until the end of the file is reached.
  • it must be implemented so that it handles any BUFFER_SIZE defined at compile time.

Bonus Requirements

  • Must use only one static variable.
  • The function must be able to handle multiple file descriptors appropriately.
  • Each function call should be able to read from different fd without loosing track of partial lines read into its static buffer.

Structure 🚧

Mandatory & Bonus w/ Arrays: Files and Functions 🗂

---
title get_next_line Mandatory & Bonus Structure
---
classDiagram
	class gnl["get_next_line.c"]
	class gnlu["get_next_line_utils.c"]
	class gnlh["get_next_line.h"]
	
	gnlh <--> gnlu
	gnlh <--> gnl

	gnl : char *get_next_line(int fd)
	gnl : static char *ft_getline(int fd, char *vault)
	gnl : static char *ft_gettillnl(char *vault)
	gnl : static char *ft_getrest(char *vault)

	gnlu : char * ft_strjoin_gnl(char *s1, char *s2)
	gnlu : char * ft_strlen_gnl(char *str)
	gnlu : char * ft_strchr_gnl(const char *s, int c)	

Mandatory w/ Linked Lists: Files and Functions 🔗

---
title get_next_line Mandatory w/ Linked Lists Structure
---
classDiagram
	class gnl["get_next_line.c"]
	class gnlu["get_next_line_utils.c"]
	class gnlh["get_next_line.h"]
	
	gnlh <--> gnlu
	gnlh <--> gnl

	gnl : char *get_next_line(int fd)
	gnl : void ft_getline(int fd, t_list **strs, int *c_read)
	gnl : void ft_storestr(t_list **strs char *buffer, int c_read)
	gnl : void ft_get_strs(t_list *strs, char *line)
	gnl : void ft_clear_strs(t_list **strs)

	gnlu : char * ft_strjoin_gnl(char *s1, char *s2)
	gnlu : char * ft_strlen_gnl(char *str)
	gnlu : char * ft_strchr_gnl(const char *s, int c)	

Usage 🏁

  1. Clone repository & enter directory:
git clone https://github.com/PedroZappa/42_get_next_line.git zedro-gnl
cd zedro-gnl

[!Note]

Two distinct implementation can be found in this repository: the one on srcll implements Linked Lists without the bonus; while the other on srcb uses Arrays and meets both mandatory and bonus requirements.


  1. To check all the available commands:
make help
  1. Compile mandatory with Arrays 🗂:
make
  1. Compile bonus with Arrays 🗂:
make bonus
  1. Compile mandatory with Linked Lists 🔗:
make extrall

[!Important]

The Linked Lists implementation does not fully pass norminette's tests. It was my first attempt at this project, I decided to keep it for future reference on handling Linked Lists. It seems impossible to solve this challenge using Linked Lists taking the appropriate precautions to avoid memory leaks while adhering to The Norm.


Debugging 🪲

Within each implementation folder there is a .gdbinit file defining commands to quickly display relevant debug info customized for each implementation. trace-commands and logging is turned on to save gdb's output into a gdb.txt file that we can track in real time with the command tail for a better debugging experience.

[!NOTE]

For user convenience the make command will copy the .gdbinit file related to the selected implementation into the root of the project.


Debugging get_next_line

  1. In your home directory, create a .gdbinit file with the following content:
set auto-load safe-path /

This command is used to set the directories from which gdb can automatically load files. When gdb starts it reads commands from several initialization files, .gdbinit being one of them, it defines the commands to be automatically executed at the start of a gdb session.

[!Important] Do this step only if you trust all the contents of the system you're working on, otherwise change / to the path of the folder you cloned this repo to.

  1. Compile your chosen get_next_line implementation, for survey convenience the -g flag is called by default at compile time:
make
# or
make bonus 
# or
make extrall
  1. Open another terminal instance and fire up valgrind and vgdb by running valgrind with the flag --vgdb-error=0:
valgrind -q --vgdb-error=0 ./a.out

vgdb is a small tool that allows gdb and valgrind to work together.

  1. On the first terminal, run gdb with the --tui flag to launch gdb with a graphical user interface:
gdb --tui ./a.out <file>
  1. On a third terminal instance run tail with the -f flag, which will keep track and print to the screen gdb's output:
tail -f gdb.txt
  1. To investigate the state of the memory at any point of execution of the program run the custom command mchk:
(gdb) mchk

This command is an alias for monitor leak_check full reachable any

[!Important]

If you use tmux give make gdb and make vgdb rules a try 😉


Happy Debugging! 🐛


License ©️

This work is published under the terms of 42 Unlicense.

(get to top)