C function fscanf with memory loss - c

I am currently using function fscanf to parse a file with some char and float point. I confirmed the results by printing them out and memory check with valgrind.
Now, the printing is correct but there are always a definitely loss of memory.
This is a sample code:
FILE* table;
table = fopen("table", "r");
double mass;
while (fscanf(table, %lf ", &mass) != EOF){
printf("mass: %lf\n", mass);
}
and the valgrind with --leak-check=full option says:
==7104== 513 bytes in 1 blocks are definitely lost in loss record 52 of 62
==7104== at 0x100008EBB: malloc (in /usr/local/Cellar/valgrind/3.11.0/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
==7104== by 0x1001EF66C: __parsefloat_buf (in /usr/lib/system/libsystem_c.dylib)
==7104== by 0x1001ED9EF: __svfscanf_l (in /usr/lib/system/libsystem_c.dylib)
==7104== by 0x1001E1492: fscanf (in /usr/lib/system/libsystem_c.dylib)
==7104== by 0x100000F3F: main (in ./prtm)
I think it's the problem of format. I've also tried to use %f and float but just get more similar error.
Can anyone tell me what goes wrong?

Although you do not fclose() to file in the code fragment posted, I doubt this is causing trouble. In any case, make sure you fclose() the file.
The function fscanf seems to allocate memory for its own purposes and does not free it at program exit. valgrind usually knows about such unavoidable memory leak and suppresses the output, for for some reason it missed this one.
This message does not seem to indicate a problem in your code. The reported lost block is allocated by the OS/X version of fscanf() as can be seen from the call stack, for its internal floating point parser __parsefloat_buf.
More precisely, the source code to the LibC is available from http://opensource.apple.com (Libc-763.11/stdio/vfscanf-fbsd.c:965) and the block should have been free'd upon exit.
You could try and free it yourself with this, but I do not recommend adding this fragment to production code.
#include <stdlib.h>
#include <pthread.h>
#include <sys/cdefs.h>
...
free(pthread_getspecific(__LIBC_PTHREAD_KEY_PARSEFLOAT));
pthread_setspecific(__LIBC_PTHREAD_KEY_PARSEFLOAT, NULL);
Instead, as pointed out by Rad Lexus, you should tell valgrind to ignore this warning as shown in this question: On OSX Valgrind reports this memory leak, Where is it coming from?

Related

Memory corruption after running malloc

I am writing a pet project (a sort of single-threaded Lisp-like language interpreter in C), and I came upon the following issue: a pointer is overwritten while malloc() is run. Showing all the code would be too long, but I can share it if necessary. I would like to have some insight regarding how the problem can be debugged.
The bug happens during the subroutine that runs a user-defined function:
/* Determine the amount of arguments to the called function */
int argc = ast_len(fn_args)
printf("%s:%d %p\n", __FILE__, __LINE__, (void*) scope->vars->tail);
/* Allocate the memory to store the array of pointers to each of the arguments */
struct YL_Var** argv = malloc(sizeof(struct YL_Var*)*argc);
printf("%s:%d %p\n", __FILE__, __LINE__, (void*) scope->vars->tail);
You will get the following output:
interpreter.c:549 0x5558371c9480
interpreter.c:551 0x411
Segmentation fault (core dumped)
The pointer scope->vars->tail is overwritten during the call to malloc()!
Using gdb and hardware break points clearly showed that the value was overwritten inside malloc.c.
As the pointer is overwritten, the program segfaults soon after, both within gdb and in normal run. However it does not segfault when run inside valgrind, it even ends successfully.
So here is my question. How would you start to debug this mess? I am asking for advice, and not for an answer.
I am far from being a C expert :)
I guess I am at fault and this is of course no bug in glibc-2.26 or gcc 7.2.0.
I have no warnings on gcc with -Wall -Wextra -Wpedantic
valgrind shows some unfreed memory issue. Will fix them before doing anything else.
Thanks to everyone's comment, I found the issue.
scope->vars was not appropriately allocated (as some said).
When using valgrind, I found the following message:
==23054== Invalid write of size 8
==23054== at 0x10A380: varlist_prepend (interpreter.c:277)
==23054== by 0x109548: main (yl.c:39)
==23054== Address 0x5572a98 is 0 bytes after a block of size 8 alloc'd
==23054== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==23054== by 0x10A304: varlist_prepend (interpreter.c:274)
==23054== by 0x109548: main (yl.c:39)
==23054==
My code looked like this:
struct YL_VarList* vars = malloc(sizeof(vars));
As you can see, the * was missing.
This is the corrected version:
struct YL_VarList* vars = malloc(sizeof(*vars));
sizeof(vars) would return the size of struct YL_VarList*, while I want to allocate the size of struct YL_VarList.

Parse command line with GLib causes Valgrind to detect invalid read

Learning Valgrind here, and also learning how to write better C.
I am trying to parse the command line of an example program using GLib's command line parsing; in fact, took almost verbatim the provided example. The only difference is that I "pop" the first element of argv and use it as a command for the rest of the program; in order to do so, I skip the first argument and copy the rest to an array char **arguments:
// file: main.c
int main(int argc, char **argv)
{
const char *allowed_cmds[] = {"greet", "teerg"};
char cmd[24];
g_stpcpy(cmd, argv[1]);
char **arguments= (char**)calloc((argc - 1), sizeof(char*));
if (check_string_in_array(cmd, allowed_cmds, 2)) {
skip_elements_from_array(argv, argc, 1, arguments);
}
char saluted[24];
read_saluted_from_command_line(argc, arguments, saluted);
free(arguments);
// ... skipped ...
return 0;
}
// file: hello.c
int read_saluted_from_command_line(int argc, char **argv, char *result)
{
gchar *saluted = "world";
GError *error = NULL;
GOptionContext *context;
GOptionEntry entries[] =
{
{ "saluted", 's', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &saluted, "person or thing to salute", "WORLD" },
{ NULL }
};
context = g_option_context_new("- Say hello to a person or thing");
g_option_context_add_main_entries(context, entries, NULL);
if (!g_option_context_parse_strv(context, &argv, &error))
{
g_error("option parsing failed: %s\n", error->message);
exit(1);
}
g_option_context_free(context);
if (error != NULL)
g_error_free(error);
g_stpcpy(result, saluted);
return 0;
}
This code compiles and runs fine, but checking with Valgrind leads to:
$ valgrind --read-var-info=yes --track-origins=yes --leak-check=full ./hello greet
==7779== Memcheck, a memory error detector
==7779== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==7779== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==7779== Command: ./hello greet
==7779==
==7779== Invalid read of size 8
==7779== at 0x4E9F303: g_strv_length (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4200.1)
==7779== by 0x4E8B0AC: g_option_context_parse_strv (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4200.1)
==7779== by 0x40128C: read_saluted_from_command_line (hello.c:54)
==7779== by 0x401753: main (main.c:68)
==7779== Address 0x597a298 is 0 bytes after a block of size 8 alloc'd
==7779== at 0x4C2AD10: calloc (vg_replace_malloc.c:623)
==7779== by 0x4016EE: main (main.c:58)
The code uses function g_option_context_parse_strv because according to documentation this function does not "assum[e] that the passed-in array is the argv of the main function". Using g_option_context_parse leads to the same message.
I am quite sure that the offending variable is arguments because it is precisely alloc'd in main:68, but I don't understand why Valgrind thinks that "your program reads or writes memory at a place which Memcheck reckons it shouldn't". Even more puzzling to me is the fact that the error disappears if I move the code from a separate function in a different file and paste it directly into main.c. Is this an error in passing the char ** to the function?
(I have found several threads on Stack Overflow that discuss Valgrind and invalid reads, but all of them deal with structs that are defined by the OP, and none have anything to do with GLib).
Thanks for any help!
Before I get to (I think) the answer: when asking for help, you should always post a complete snippet which people can compile and run themselves (i.e., a SSCCE). Also, when looking at valgrind logs, it's important to make sure to post a complete example so people can see exactly where the warnings are coming from.
Based on what you've posted, the problem is that g_option_context_parse_strv expects a NULL-terminated array. Since you're not also passing a length, that is the only way for glib to know what is the array. As it is, since it doesn't encounter a NULL element glib will continue reading past the end of the array into uninitialized memory, which is where valgrind (rightfully) complains. You need to allocate room for an extra element in arguments and set it to NULL.
As for David's comment about glib and valgrind not getting along, it's very important to keep in mind that this is only the case for leaks, and even then only for certain types of leaks. Warnings about accessing uninitialized and/or invalid memory are every bit as "real" in glib-based programs as anywhere else. It's dangerous to simply disregard valgrind's output (or AddressSanitizer, or other similar tools) without understanding that.
The limitation in valgrind with leaks is that GLib allocates a small amount of memory for type information which is shared by every instance of a type. This information is never freed, though it is still accessible (which is why valgrind lists it as possibly lost, not definitely lost). Basically, you can usually disregard warnings about allocations coming from a g_gtype_* function being possibly lost, but that's it.
The reason information is never freed because doing so would simply waste performance. Obviously you would need to know when to free it, which means keeping track of whether or not it is still in use. That means either a tracing garbage collector (which isn't really an option for a C library), or reference counting. Reference counting requires keeping a counter synchronized across multiple cores and cache levels (and possibly other CPUs), which is a huge performance drain and very much not worth it just to avoid some easy-to-identify false positives in a couple tools (like valgrind and AddressSanitizer).

Segmentation fault from pointer in fprintf

I am trying to run a program that takes an input file, reads it, and then runs a simulation based on the parameters specified in the input file. The code is a mixture of C and Fortran77, with the main executable entirely in Fortran77. I did not write the code and I'm inexperienced with both languages (so if I say something stupid, that's why).
Upon running the program, I get the following error regardless of the input file: Segmentation fault (core dumped)
This is the output I get from valgrind, with a few small omissions:
Invalid read of size 4
at 0x55ACFDD: vfprintf (vfprintf.c:1295)
by 0x55B76B6: fprintf (fprintf.c:32)
by 0x578C64: cfprintf_ (in [path omitted])
by 0x56D288: writebuf_ (writebuf.F:22)
by 0x56D3CC: writemsg_ (writemsg.F:15)
by 0x4C09E7: init0_ (init0.F:68)
by 0x4D6C65: [omitted]
by 0x4E9EC4: main (main.c:113)
Address 0xffffffff0592bbc0 is not stack'd, malloc'd or (recently) free'd
Process terminating with default action of signal 11 (SIGSEGV)
Access not within mapped region at address 0xFFFFFFFF0592BBC0
at 0x55ACFDD: vfprintf (vfprintf.c:1295)
by 0x55B76B6: fprintf (fprintf.c:32)
by 0x578C64: cfprintf_ (in [path omitted])
by 0x56D288: writebuf_ (writebuf.F:22)
by 0x56D3CC: writemsg_ (writemsg.F:15)
by 0x4C09E7: init0_ (init0.F:68)
by 0x4D6C65: [omitted]
by 0x4E9EC4: main (main.c:113)
If you believe this happened as a result of a stack
overflow in your program's main thread (unlikely but
possible), you can try to increase the size of the
main thread stack using the --main-stacksize= flag.
The main thread stack size used in this run was 8388608.
HEAP SUMMARY:
in use at exit: 11,354 bytes in 7 blocks
total heap usage: 46 allocs, 39 frees, 22,590 bytes allocated
LEAK SUMMARY:
definitely lost: 0 bytes in 0 blocks
indirectly lost: 0 bytes in 0 blocks
possibly lost: 8,008 bytes in 2 blocks
still reachable: 3,346 bytes in 5 blocks
suppressed: 0 bytes in 0 blocks
Rerun with --leak-check=full to see details of leaked memory
For counts of detected and suppressed errors, rerun with: -v
ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
It seems the vfprintf.c and fprintf.c files are part of some internal library, because I can't find those files on my computer. cfprintf.c is part of my code, shown below:
#include <stdio.h>
#include <fcntl.h>
#ifdef _CRAY
#ifdef FORTRAN_PASSES_ASSUMED_CHAR_LEN
int CFPRINTF (fileptr, s1, cl1, num_chars)
int *cl1;
#else
int CFPRINTF (fileptr, s1, num_chars)
#endif
#else
#ifdef POST_UNDERSCORE
int cfprintf_ (fileptr, s1, num_chars)
#else
int cfprintf (fileptr, s1, num_chars)
#endif
#endif
/* write num_chars characters from string s1 to file associated with fileptr */
FILE **fileptr;
char *s1;
int *num_chars;
{
char format_string [11];
char buffer[256];
sprintf (format_string, "%c.%ds", '%', *num_chars);
/* write to an intermediate buffer to avoid problems with '\n' */
sprintf (buffer, format_string, s1);
fprintf (*fileptr, "%s\n", buffer);
}
The line that throws the error is fprintf (*fileptr, "%s\n", buffer);
Specifically, I think it's the pointer that is causing the error, but I don't what's wrong or how to fix it.
I had issues compiling the code initially because I am using a 64-bit machine. The code, which relies heavily on pointers, implicitly declares many if not all of them, so I think that means they take the default 32-bit format of 4-bit integers. However, on my machine these pointers are 8-bit integers because I compiled in 64 bits.
If *fileptr is of one format, but the code is expecting another, perhaps that is what's generating the Invalid read of size 4 message from valgrind? But like I said, if that's the problem I still don't know how to fix it.
Thanks for your help, and please let me know if there's any additional code I should post.
First of all, you definitely shouldn't be constructing your format string at runtime like that. Use the following instead:
snprintf(buffer, 256, "%.*s", *num_chars, s1);
or even just
fprintf(*fileptr, "%.*s\n", *num_chars, s1);
.* allows the width of the string to be dynamically specified.
Next, I would check that your fileptr is valid, and that it was successfully opened. The address 0xffffffff0592bbc0 is very suspicious due to the four high bytes all being 0xff, so it is possible that you are having 32-bit/64-bit issues.
As I understand from your question, the application has been known to work in the past, but compiled on 32-bit Unix systems? (That's the only environment I've seen old Fortran and C code mixed in a single program in general.)
Unless you want to port the application to 64-bit I would suggest you simply compile it as an 32-bit native application, assuming your operating system allows 32-bit applications to run in a 64-bit environment.
For example using the gcc compiler the flag -m32 is all you need to add for 64-bit x86 processor systems. I believe clang supports the same flag, but if not check the documentation.
A second potential complicating factor, is whether the program / application (or its data) is endian dependent, which may be an issue if was written under the assumption of being run on BIG ENDIAN CPUs, such as the majority of Unix workstations with RISC-style processors (MIPS, PowerPC, etc.), and you are now trying to run it on an 64-bit x86 Intel or AMD processor (aka amd64, x86-64).
My advice in this case is to hurt someone..., er, review the important of the application and its usage.

How do I use valgrind to find memory leaks?

How do I use valgrind to find the memory leaks in a program?
Please someone help me and describe the steps to carryout the procedure?
I am using Ubuntu 10.04 and I have a program a.c, please help me out.
How to Run Valgrind
Not to insult the OP, but for those who come to this question and are still new to Linux—you might have to install Valgrind on your system.
sudo apt install valgrind # Ubuntu, Debian, etc.
sudo yum install valgrind # RHEL, CentOS, Fedora, etc.
sudo pacman -Syu valgrind # Arch, Manjaro, Garuda, etc
Valgrind is readily usable for C/C++ code, but can even be used for other
languages when configured properly (see this for Python).
To run Valgrind, pass the executable as an argument (along with any
parameters to the program).
valgrind --leak-check=full \
--show-leak-kinds=all \
--track-origins=yes \
--verbose \
--log-file=valgrind-out.txt \
./executable exampleParam1
The flags are, in short:
--leak-check=full: "each individual leak will be shown in detail"
--show-leak-kinds=all: Show all of "definite, indirect, possible, reachable" leak kinds in the "full" report.
--track-origins=yes: Favor useful output over speed. This tracks the origins of uninitialized values, which could be very useful for memory errors. Consider turning off if Valgrind is unacceptably slow.
--verbose: Can tell you about unusual behavior of your program. Repeat for more verbosity.
--log-file: Write to a file. Useful when output exceeds terminal space.
Finally, you would like to see a Valgrind report that looks like this:
HEAP SUMMARY:
in use at exit: 0 bytes in 0 blocks
total heap usage: 636 allocs, 636 frees, 25,393 bytes allocated
All heap blocks were freed -- no leaks are possible
ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
I have a leak, but WHERE?
So, you have a memory leak, and Valgrind isn't saying anything meaningful.
Perhaps, something like this:
5 bytes in 1 blocks are definitely lost in loss record 1 of 1
at 0x4C29BE3: malloc (vg_replace_malloc.c:299)
by 0x40053E: main (in /home/Peri461/Documents/executable)
Let's take a look at the C code I wrote too:
#include <stdlib.h>
int main() {
char* string = malloc(5 * sizeof(char)); //LEAK: not freed!
return 0;
}
Well, there were 5 bytes lost. How did it happen? The error report just says
main and malloc. In a larger program, that would be seriously troublesome to
hunt down. This is because of how the executable was compiled. We can
actually get line-by-line details on what went wrong. Recompile your program
with a debug flag (I'm using gcc here):
gcc -o executable -std=c11 -Wall main.c # suppose it was this at first
gcc -o executable -std=c11 -Wall -ggdb3 main.c # add -ggdb3 to it
Now with this debug build, Valgrind points to the exact line of code
allocating the memory that got leaked! (The wording is important: it might not
be exactly where your leak is, but what got leaked. The trace helps you find
where.)
5 bytes in 1 blocks are definitely lost in loss record 1 of 1
at 0x4C29BE3: malloc (vg_replace_malloc.c:299)
by 0x40053E: main (main.c:4)
Techniques for Debugging Memory Leaks & Errors
Make use of www.cplusplus.com! It has great documentation on C/C++ functions.
General advice for memory leaks:
Make sure your dynamically allocated memory does in fact get freed.
Don't allocate memory and forget to assign the pointer.
Don't overwrite a pointer with a new one unless the old memory is freed.
General advice for memory errors:
Access and write to addresses and indices you're sure belong to you. Memory
errors are different from leaks; they're often just IndexOutOfBoundsException
type problems.
Don't access or write to memory after freeing it.
Sometimes your leaks/errors can be linked to one another, much like an IDE discovering that you haven't typed a closing bracket yet. Resolving one issue can resolve others, so look for one that looks a good culprit and apply some of these ideas:
List out the functions in your code that depend on/are dependent on the
"offending" code that has the memory error. Follow the program's execution
(maybe even in gdb perhaps), and look for precondition/postcondition errors. The idea is to trace your program's execution while focusing on the lifetime of allocated memory.
Try commenting out the "offending" block of code (within reason, so your code
still compiles). If the Valgrind error goes away, you've found where it is.
If all else fails, try looking it up. Valgrind has documentation too!
A Look at Common Leaks and Errors
Watch your pointers
60 bytes in 1 blocks are definitely lost in loss record 1 of 1
at 0x4C2BB78: realloc (vg_replace_malloc.c:785)
by 0x4005E4: resizeArray (main.c:12)
by 0x40062E: main (main.c:19)
And the code:
#include <stdlib.h>
#include <stdint.h>
struct _List {
int32_t* data;
int32_t length;
};
typedef struct _List List;
List* resizeArray(List* array) {
int32_t* dPtr = array->data;
dPtr = realloc(dPtr, 15 * sizeof(int32_t)); //doesn't update array->data
return array;
}
int main() {
List* array = calloc(1, sizeof(List));
array->data = calloc(10, sizeof(int32_t));
array = resizeArray(array);
free(array->data);
free(array);
return 0;
}
As a teaching assistant, I've seen this mistake often. The student makes use of
a local variable and forgets to update the original pointer. The error here is
noticing that realloc can actually move the allocated memory somewhere else
and change the pointer's location. We then leave resizeArray without telling
array->data where the array was moved to.
Invalid write
1 errors in context 1 of 1:
Invalid write of size 1
at 0x4005CA: main (main.c:10)
Address 0x51f905a is 0 bytes after a block of size 26 alloc'd
at 0x4C2B975: calloc (vg_replace_malloc.c:711)
by 0x400593: main (main.c:5)
And the code:
#include <stdlib.h>
#include <stdint.h>
int main() {
char* alphabet = calloc(26, sizeof(char));
for(uint8_t i = 0; i < 26; i++) {
*(alphabet + i) = 'A' + i;
}
*(alphabet + 26) = '\0'; //null-terminate the string?
free(alphabet);
return 0;
}
Notice that Valgrind points us to the commented line of code above. The array
of size 26 is indexed [0,25] which is why *(alphabet + 26) is an invalid
write—it's out of bounds. An invalid write is a common result of
off-by-one errors. Look at the left side of your assignment operation.
Invalid read
1 errors in context 1 of 1:
Invalid read of size 1
at 0x400602: main (main.c:9)
Address 0x51f90ba is 0 bytes after a block of size 26 alloc'd
at 0x4C29BE3: malloc (vg_replace_malloc.c:299)
by 0x4005E1: main (main.c:6)
And the code:
#include <stdlib.h>
#include <stdint.h>
int main() {
char* destination = calloc(27, sizeof(char));
char* source = malloc(26 * sizeof(char));
for(uint8_t i = 0; i < 27; i++) {
*(destination + i) = *(source + i); //Look at the last iteration.
}
free(destination);
free(source);
return 0;
}
Valgrind points us to the commented line above. Look at the last iteration here,
which is *(destination + 26) = *(source + 26);. However, *(source + 26) is
out of bounds again, similarly to the invalid write. Invalid reads are also a
common result of off-by-one errors. Look at the right side of your assignment
operation.
The Open Source (U/Dys)topia
How do I know when the leak is mine? How do I find my leak when I'm using
someone else's code? I found a leak that isn't mine; should I do something? All
are legitimate questions. First, 2 real-world examples that show 2 classes of
common encounters.
Jansson: a JSON library
#include <jansson.h>
#include <stdio.h>
int main() {
char* string = "{ \"key\": \"value\" }";
json_error_t error;
json_t* root = json_loads(string, 0, &error); //obtaining a pointer
json_t* value = json_object_get(root, "key"); //obtaining a pointer
printf("\"%s\" is the value field.\n", json_string_value(value)); //use value
json_decref(value); //Do I free this pointer?
json_decref(root); //What about this one? Does the order matter?
return 0;
}
This is a simple program: it reads a JSON string and parses it. In the making,
we use library calls to do the parsing for us. Jansson makes the necessary
allocations dynamically since JSON can contain nested structures of itself.
However, this doesn't mean we decref or "free" the memory given to us from
every function. In fact, this code I wrote above throws both an "Invalid read"
and an "Invalid write". Those errors go away when you take out the decref line
for value.
Why? The variable value is considered a "borrowed reference" in the Jansson
API. Jansson keeps track of its memory for you, and you simply have to decref
JSON structures independent of each other. The lesson here:
read the documentation. Really. It's sometimes hard to understand, but
they're telling you why these things happen. Instead, we have
existing questions about this memory error.
SDL: a graphics and gaming library
#include "SDL2/SDL.h"
int main(int argc, char* argv[]) {
if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO) != 0) {
SDL_Log("Unable to initialize SDL: %s", SDL_GetError());
return 1;
}
SDL_Quit();
return 0;
}
What's wrong with this code? It consistently leaks ~212 KiB of memory for me. Take a moment to think about it. We turn SDL on and then off. Answer? There is nothing wrong.
That might sound bizarre at first. Truth be told, graphics are messy and sometimes you have to accept some leaks as being part of the standard library. The lesson here: you need not quell every memory leak. Sometimes you just need to suppress the leaks because they're known issues you can't do anything about. (This is not my permission to ignore your own leaks!)
Answers unto the void
How do I know when the leak is mine?
It is. (99% sure, anyway)
How do I find my leak when I'm using someone else's code?
Chances are someone else already found it. Try Google! If that fails, use the skills I gave you above. If that fails and you mostly see API calls and little of your own stack trace, see the next question.
I found a leak that isn't mine; should I do something?
Yes! Most APIs have ways to report bugs and issues. Use them! Help give back to the tools you're using in your project!
Further Reading
Thanks for staying with me this long. I hope you've learned something, as I tried to tend to the broad spectrum of people arriving at this answer. Some things I hope you've asked along the way: How does C's memory allocator work? What actually is a memory leak and a memory error? How are they different from segfaults? How does Valgrind work? If you had any of these, please do feed your curiousity:
More about malloc, C's memory allocator
Definition of a segmentation fault
Definition of a memory leak
Definition of a memory access error
How does Valgrind work?
Try this:
valgrind --leak-check=full -v ./your_program
As long as valgrind is installed it will go through your program and tell you what's wrong. It can give you pointers and approximate places where your leaks may be found. If you're segfault'ing, try running it through gdb.
You can run:
valgrind --leak-check=full --log-file="logfile.out" -v [your_program(and its arguments)]
You can create an alias in .bashrc file as follows
alias vg='valgrind --leak-check=full -v --track-origins=yes --log-file=vg_logfile.out'
So whenever you want to check memory leaks, just do simply
vg ./<name of your executable> <command line parameters to your executable>
This will generate a Valgrind log file in the current directory.

Cannot free memory after using strdup

gcc 4.5.1 c89
I am trying to free some memory. However, when I check with valgrind the memory hasn't been freed. I am wondering what I am doing wrong.
I have the following structure:
typedef struct tag_cand_results {
char *candidate_winners[NUMBER_OF_CANDIDATES];
} cand_results;
I create an object of this structure:
cand_results *results = NULL;
I allocate some memory for the structure.
results = calloc(1, sizeof *results);
Assign some data to it
results->candidate_winners[0] = strdup("Steve Martin");
results->candidate_winners[1] = strdup("Jack Jones");
Then I try to free all the memory allocated:
free(results->candidate_winners[0]);
free(results->candidate_winners[1]);
free(results);
Just to be safe assign to NULL
results = NULL;
I get the following output from valgrind.
==8119== 72 bytes in 6 blocks are definitely lost in loss record 1 of 2
==8119== at 0x4A05E46: malloc (vg_replace_malloc.c:195)
==8119== by 0x3FE2E82A91: strdup (strdup.c:43)
==8119== by 0x400E5A: main (driver.c:116)
==8119==
==8119== 72 bytes in 6 blocks are definitely lost in loss record 2 of 2
==8119== at 0x4A05E46: malloc (vg_replace_malloc.c:195)
==8119== by 0x3FE2E82A91: strdup (strdup.c:43)
==8119== by 0x400E72: main (driver.c:117)
I don't know why the memory is not been freed?
Many thanks for any suggestions,
If that is actually the sequence of events, then valgrind is wrong. The memory is being freed.
As to the best technique requested in your comment, normally I would say valgrind but perhaps not in this case :-)
Some things to check.
What happens if you just call malloc(30) instead of strdup(some_string) (in both cases)?
Remove the (malloc-or-strdup)/free pairs one at a time to see what happens.
I haven't seen your actual code so put a printf before and after every strdup and free line to make sure they're all being run.
Post a full small program here (that exhibits the problem) so we can check it out.
For what it's worth, the following small (complete) program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NUMBER_OF_CANDIDATES 10
typedef struct tag_cand_results {
char *candidate_winners[NUMBER_OF_CANDIDATES];
} cand_results;
int main (void) {
cand_results *results = NULL;
results = calloc(1, sizeof *results);
results->candidate_winners[0] = strdup("Steve Martin");
results->candidate_winners[1] = strdup("Jack Jones");
free(results->candidate_winners[0]);
free(results->candidate_winners[1]);
free(results);
results = NULL;
return 0;
}
results in the following valgrind output:
==9649== Memcheck, a memory error detector
==9649== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==9649== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for
copyright info
==9649== Command: ./qq
==9649==
==9649==
==9649== HEAP SUMMARY:
==9649== in use at exit: 0 bytes in 0 blocks
==9649== total heap usage: 3 allocs, 3 frees, 64 bytes allocated
==9649==
==9649== All heap blocks were freed -- no leaks are possible
==9649==
==9649== For counts of detected and suppressed errors, rerun with: -v
==9649== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 13 from 8)
In other words, no problems. So it may be something else in your case (an environment issue perhaps). This particular run was done on Ubuntu Lucid (10.04), gcc 4.4.3, c89 mode.
I'd suggest typing in that code exactly on your system to see what happens. The command line I used to compile and test was:
gcc -std=c89 -o qq qq.c
valgrind ./qq
You can also debug your application with gdb and watch if any pointer gets changed with the "watch" command. Place a breakpoint on your main function and do a step by step followup to discover where the problem resides.
Regards,
Miguel
There is no obvious error in your allocations/frees.
It looks like the content of result has been changed somehow (overwritten by some wild pointer ?).
One easy way to check that is to print memory address values of pointer (using printf("%p", ...)) immediately after the allocation using strdup and just before freeing. If it changed : bingo!
Do it also with result, another explanation could be that the pointer to result has changed (and henceforth the values pointed to).
Now, if the pointer has indeed changed how to pinpoint where it occurs ?
One solution can be to run the program using a debugger. This can be very time consuming in some case, but it usually works. But if this is not an option, there is another way. I usually find it faster than using a debugger.
Keep a copy of the allocated pointer in another variable, preferably make it remote from the memory chunk where is your corrupted pointer (a global will usually do).
Now in the control flow put assertions like:
assert(result == saved_result);
At some place the assertion should fail and you will eventually find the problem.
Aftwerward, you should not forget to remove your assertions that should not be left in the final project. To be sure of that just remove the saved_result variable. The program won't compile in debug mode if any assertion is left.
"72 bytes in 6 blocks", doesn't sound like "Steve Martin" or "Jack Jones". You're not overwriting the pointers at some point(!)?

Resources