F'up2 clc
Pedro said:
Ok. I posted the code to
<
http://hexkid.blogspot.com/2006/02/memory-management-in-c.html>
My real question is if the program does not have memory leaks or some
other bad things with the allocation calls.
Other than that, any other hints/tips on how to do things better would
be very much appreciated.
I will comment on your main() function, so I quote that part here:
/* main.c
*
* Pedro Graca, 2006-02-09
* This code is in the public domain
* */
#include <stdio.h>
#include <stdlib.h>
#include "selfref.h"
int main(int argc, char * argv[])
char ** argv
is clearer.
{
char *** synonyms = NULL;
FILE * fp;
char line[MAX_LINE_LENGTH + 1];
if (argc < 2) {
fprintf(stderr, "Usage: %s FILENAME\n", argv[0]);
Note: argv[0] can be NULL. Make this
argv[0] ? argv[0] : said:
Here, you have finished validating the input. Now, the real
thing starts. Put it into a function (with const char *
parameter) and call this function.
fp = fopen(argv[1], "r");
if (!fp) {
fprintf(stderr, "Unable to open file.\n");
exit(EXIT_FAILURE);
}
while (fgets(line, MAX_LINE_LENGTH, fp)) {
if (parse_line(line, &synonyms))
fprintf(stderr, "Oops\n");
}
fclose(fp);
Note: If the file is completely empty, synonyms may still
be NULL here.
The same for errors in parse_line().
Obviously (by looking below, too), parse_line() does 2 things:
- If synonyms==NULL: Allocate synonyms (and maybe set
synonyms[0]=NULL); set some internal "line number" counter to 0.
- Always: replace synonyms[line number] by a pointer to the
parsed stuff, increase line number, set synonyms[line number]=NULL
This is one thing too much.
Break this down into
1) initialisation,
2) parsing, and
3) adding another item to the synonyms array.
{ /* validate program */
int nidx=0, syn_idx;
while (synonyms[nidx]) {
If synonyms is NULL, this will go terribly wrong.
syn_idx = 0;
printf("%d: ", nidx);
while (synonyms[nidx][syn_idx]) {
printf("%s", synonyms[nidx][syn_idx]);
++syn_idx;
if (synonyms[nidx][syn_idx])
printf(", ");
}
++nidx;
printf("\n");
}
}
Make this a function of its own.
{ /* free memory */
int nidx=0, syn_idx;
while (synonyms[nidx]) {
syn_idx = 0;
while (synonyms[nidx][syn_idx]) {
free(synonyms[nidx][syn_idx]);
++syn_idx;
}
free(synonyms[nidx][syn_idx]);
free(synonyms[nidx]);
++nidx;
}
free(synonyms[nidx]);
You forget to free(synonyms);
Rule of thumb: The role that allocates the stuff, frees the
stuff. Provide a dedicated allocation handling and an
accompanying deallocation function.
#ifdef _WIN32
printf("Press <ENTER>\n");
getchar();
#endif
Fair enough.
All in all, rather nice.
Work at the design and break things down into easily testable
functions. Step 2: Have a test for these functions.
PS. I had to tweak the code a bit (the '<'s and the '&'s) to have it
display properly. Hope it doesn't become an uncompilable mess for people
who copy/paste it to their computers.
Provide a "nice to look at" as well as a download version.
Note: Consider using ggets()/fggets() for reading the lines.
These are non-standard but there is at least one public domain
version (by Chuck Falconer).
Advantage: No line length restriction, automatic allocation of
the memory for the line (which means no unnecessary copying in
your case).
I have looked only shortly at the actual selfref.c and
parse_line(). Do not try to save lines by putting if and
the statement following if (condition) in one line.
This easily can obscure things. Especially if one loses
indentation copying over your source from the browser.
The same holds for loops etc, too.
Cheers
Michael