For example, you malloc in your get_line function but you free in main. I would probably do your line handling in main so the malloc/free are in the same scope.
Alternatively, I will sometimes make Create and Destroy functions that do the allocating/freeing but even when I do that I always try to keep the calls within the same scope so it's not easy to loose track of memory.
Practically allocating/freeing in the same scope is difficult so it takes a lot of effort to structure your code to accommodate.
If you're interested in mission-critical C programming you should check out the JPL C standards: http://lars-lab.jpl.nasa.gov/JPL_Coding_Standard_C.pdf
They're a little unrealistic for most non-space projects but it gives you a good idea of how safety-critical software is written in C.
I also do a lot of embedded C, and can confirm that dynamic allocation is rare, so why not try restructuring your program to avoid it? It's good practice and will sharpen your skills by raising all sorts of questions like why dynamic allocation is discouraged in embedded systems in the first place, and what alternatives there are, and how to use a profiler to compare different trade-offs. Heaps of exploratory fun to be had!
And hey, Graph-Reply is really cool, and so are space robots.
https://github.com/incrediblesound/Graph-Reply/commits?autho...