I am learning C programming. As a newbie, I have to say this language is really tough, especially memory management. I used to program with Java and Python, which you don't have to worry about memory leakage. However, it's totally another story with C. Recently I wrote a small program and I ran it with valgrind which said the program caused memory leak. The code is pasted.
#include <stdio.h>
#include <glib.h>
#include <string.h>
#define MAX_LENGTH 256
#define TOKEN_NUM 2
char *tokArr[MAX_LENGTH];
char** strSplit(char *oneStr, const char* delim)
{
char *localStr = oneStr;
int index = 0;
char *token = strtok(localStr, delim);
while (token != NULL) {
tokArr[index++] = token;
token = strtok(NULL, delim);
}
free(token);
return tokArr;
}
void printHash(gpointer key, gpointer val, gpointer userData)
{
printf(userData, key, val);
free(key);
free(val);
}
int main(int argc, char const *argv[])
{
if (argc != 2) {
printf("need a file name as an argument");
return -1;
}
const char *filePath = argv[1];
FILE *fp = fopen(filePath, "r");
if (fp == NULL) {
printf("error: cannot open document %s", filePath);
return -1;
}
GHashTable* hash = g_hash_table_new(g_str_hash, g_str_equal);
char buffer[MAX_LENGTH];
while (fgets(buffer, MAX_LENGTH, fp)) {
char **splitedStr = strSplit(buffer, "@@@@");
char *key = strdup(splitedStr[0]);
char *val = strdup(splitedStr[1]);
g_hash_table_insert(hash, key, val);
free(splitedStr);
}
fclose(fp);
g_hash_table_foreach(hash, (GHFunc)printHash, "Name: %s, age: %s\n");
g_hash_table_destroy(hash);
return 0;
}
As you see, this program is pretty simply. It reads in a text file line by line. Then each line will be split into two parts which are separated by a string "@@@@". Next, the first part of the line is stored into a hash table as the key with the second part of the line as the value. The hash table provided by GLib-2.0 was utilized in this program.
I tried my best to free all possible malloc memories, however, memory leak warnings still popping out. Would anyone help me to figure which parts caused the problem? Many thanks.
Unclear why someone would recommend to "stay away" from specific libraries. Just RTFM and try to understand what you are dealing with. After all, these libraries themselves could contain memory leaks... You should have a look at Electric Fence, which replaces malloc calls by something more debug-friendly: https://elinux.org/Electric_Fence
Your code could be simplified when keeping in mind that strings are always NUL-terminated. Avoiding memory copies at all, you do not need to use
strdup()and work on your input buffer alone.keypointer is always the beginning of the buffer, so just get a point to it and replace the first@character by0x00.valpointer starts after the search pattern, so you can also just get a pointer to the memory location after the last@character.buffer[MAX_LENGTH] = 0;In order to get acquainted with the way this is done in C, I recommend that you implement the pattern matching at a very basic level. Create a while loop that scans through every character in your buffer and searches for the separation pattern. When it hits 4 times in a row, you have found your pointer.
PS: If you prefer a more convenient solution, try
fscanf()instead offgets().EDIT: The documentation on GHashTable recommends to use
g_strdup(), however reading the entire file into memory would still work as described above. The buffer should be allocated usingmalloc()and may be enlarged usingrealloc()after every invocation offgets(). Special care should be taken when a line is longer thanMAX_LENGTH. It is also advisable to only increase the buffer size byMAX_LENGTHplus the number of bytes already read in i.e. from callingftell().Since
keyis a pointer to the buffer, it can be passed tofree()when destroying the hash table. If you usedrealloc(), this is only needed once with the pointer returned frommalloc().