Is there a straight forward way to mark a memory region temporarily as "Read Only" in valgrind, similar to VALGRIND_MAKE_MEM_NOACCESS?
As an Example:
==942339== Memcheck, a memory error detector
==942339== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==942339== Using Valgrind-3.16.1 and LibVEX; rerun with -h for copyright info
==942339== Command: ./a.out
==942339==
==942339== Invalid read of size 4
==942339== at 0x40085C: main (example.c:10)
==942339== Address 0x1ffeffe724 is 0 bytes inside a READING IS ALLOWED IN THIS BLOCK of size 4 client-defined
==942339== at 0x4007E0: main (example.c:7)
==942339==
==942339== Invalid read of size 4
==942339== at 0x400862: main (example.c:11)
==942339== Address 0x1ffeffe724 is 0 bytes inside a READING IS ALLOWED IN THIS BLOCK of size 4 client-defined
==942339== at 0x4007E0: main (example.c:7)
==942339==
==942339== Invalid write of size 4
==942339== at 0x400868: main (example.c:11)
==942339== Address 0x1ffeffe724 is 0 bytes inside a READING IS ALLOWED IN THIS BLOCK of size 4 client-defined
==942339== at 0x4007E0: main (example.c:7)
==942339==
==942339== Invalid read of size 4
==942339== at 0x400A31: main (example.c:18)
==942339== Address 0x1ffeffe724 is 0 bytes inside a READING AND WRITING IS FORBIDDEN IN THIS BLOCK of size 4 client-defined
==942339== at 0x4009B5: main (example.c:15)
==942339==
==942339== Invalid read of size 4
==942339== at 0x400A37: main (example.c:19)
==942339== Address 0x1ffeffe724 is 0 bytes inside a READING AND WRITING IS FORBIDDEN IN THIS BLOCK of size 4 client-defined
==942339== at 0x4009B5: main (example.c:15)
==942339==
==942339== Invalid write of size 4
==942339== at 0x400A3D: main (example.c:19)
==942339== Address 0x1ffeffe724 is 0 bytes inside a READING AND WRITING IS FORBIDDEN IN THIS BLOCK of size 4 client-defined
==942339== at 0x4009B5: main (example.c:15)
==942339==
==942339==
==942339== HEAP SUMMARY:
==942339== in use at exit: 0 bytes in 0 blocks
==942339== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==942339==
==942339== All heap blocks were freed -- no leaks are possible
==942339==
==942339== For lists of detected and suppressed errors, rerun with: -s
==942339== ERROR SUMMARY: 6 errors from 6 contexts (suppressed: 0 from 0)
But don't want the first 2 errors of this report to be considered errors.
The example code:
#include "memcheck.h"
int main(int argc, char **argv) {
int a = 10;
int b =0;
int valgrind_handle = VALGRIND_CREATE_BLOCK(&a, sizeof(a),
"READING IS ALLOWED IN THIS BLOCK");
VALGRIND_MAKE_MEM_NOACCESS(&a, sizeof(a));
b=a;// allowed to read a
a++;// forbidden to write a
VALGRIND_MAKE_MEM_DEFINED(&a, sizeof(a));
a++;// allowed
VALGRIND_DISCARD(valgrind_handle);
valgrind_handle = VALGRIND_CREATE_BLOCK(&a, sizeof(a),
"READING AND WRITING IS FORBIDDEN IN THIS BLOCK");
VALGRIND_MAKE_MEM_NOACCESS(&a, sizeof(a));
b=a;// forbidden
a++;// forbidden
VALGRIND_MAKE_MEM_DEFINED(&a, sizeof(a));
VALGRIND_DISCARD(valgrind_handle);
return 0;
}
Is there a better way than manually post-process the output to filter the unwanted errors based on the given block-names?
Related
I am working with parallel processes, and in one part of my code I want to fork a new process that calls the same program with slightly different arguments. For example, if the user initially called "./prog arg1 arg2 arg3", I would like to fork a new process that execs "./prog -n 1 arg2 arg3" and then that program would fork and exec "./prog -n 2 arg3." The only way I can think of doing this is using execv(), but I'm running into issues because execv requires that the last element in the argv[] array passed to it be NULL. Below is my code, and I will post the valgrind output below that.
//fork an additional process: ./prog -n (i+1) args...
// could accomplish by execv("./prog", paramlist), where paramlist is
// the same as -n (i+1) and then argv, skipping argv[1]
//create new paramlist
char **params = malloc(sizeof(char*) * argc + 2 );
sprintf(numbuf, "%d", i+1);
//./prog -n (i+1) argv[2:argc-1]
params[0] = argv[0];
params[1] = "-n";
params[2] = numbuf;
for(int i = 2; i<argc; i++){ //skip argv[0] bc we already assigned it
params[i+1] = argv[i]; //skip argv[1] because we just worked on it
}
params[argc+1] = NULL; //list must be null terminated
pid3 = fork();
if(0 == pid3){
execv("./prog", params);
exit(-1);
} //no waitpid here, because we'd like this process to continue on its own
params[argc+1] = ""; //avoid invalid free
free(params);
When I run this code normally, I get the following error:
*** Error in `./prog': free(): invalid next size (fast): 0x0000000001ac3830 ***
Valgrind tells me this:
==28067== Memcheck, a memory error detector
==28067== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==28067== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==28067== Command: ./prog ./photos/photo1.jpg
==28067==
=====Displaying photo 0 (be patient.. XQuartz sucks)
Enter degrees to rotate image(0,90,180,270): 90
Enter a caption > thumb
==28067== Invalid write of size 8
==28067== at 0x400C58: main (in /usr/prog)
==28067== Address 0x51fa8d0 is 16 bytes inside a block of size 18 alloc'd
==28067== at 0x4C2BBAD: malloc (vg_replace_malloc.c:299)
==28067== by 0x400C05: main (in /usr/prog)
==28067==
==28067== Invalid write of size 8
==28067== at 0x400CC3: main (in /usr/prog)
==28067== Address 0x51fa8d8 is 6 bytes after a block of size 18 alloc'd
==28067== at 0x4C2BBAD: malloc (vg_replace_malloc.c:299)
==28067== by 0x400C05: main (in /usr/prog)
==28067==
==28067== Invalid write of size 8
==28067== at 0x400D0E: main (in /usr/prog)
==28067== Address 0x51fa8d8 is 6 bytes after a block of size 18 alloc'd
==28067== at 0x4C2BBAD: malloc (vg_replace_malloc.c:299)
==28067== by 0x400C05: main (in /usr/prog)
==28067==
==28071== Syscall param execve(argv) points to unaddressable byte(s)
==28071== at 0x4F00CF7: execve (in /usr/lib64/libc-2.23.so)
==28071== by 0x400CE8: main (in /usr/prog)
==28071== Address 0x51fa8d2 is 0 bytes after a block of size 18 alloc'd
==28071== at 0x4C2BBAD: malloc (vg_replace_malloc.c:299)
==28071== by 0x400C05: main (in /usr/prog)
==28071==
==28067==
==28067== HEAP SUMMARY:
==28067== in use at exit: 0 bytes in 0 blocks
==28067== total heap usage: 5 allocs, 5 frees, 1,051,194 bytes allocated
==28067==
==28067== All heap blocks were freed -- no leaks are possible
==28067==
==28067== For counts of detected and suppressed errors, rerun with: -v
==28067== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)
Interestingly, if I comment out the 'free(params)' line, then I get a segmentation fault, occurring on the line before it, 'params[argc+1] = "";' . Why is could that be?
char **params = malloc(sizeof(char*) * argc + 2 );
Should be
char **params = malloc(sizeof(char*) * (argc + 2) );
I have a function which prints the whole content of the file and the function seems to work fine, but valgring complains about Conditional jump or move depends on uninitialised value(s) and Uninitialised value was created by a heap allocation:
==7876== Memcheck, a memory error detector
==7876== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==7876== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==7876== Command: ./program
==7876==
==7876== Conditional jump or move depends on uninitialised value(s)
==7876== at 0x4E864B2: vfprintf (vfprintf.c:1642)
==7876== by 0x4E8CC38: printf (printf.c:33)
==7876== by 0x40074C: main (program.c:45)
==7876== Uninitialised value was created by a heap allocation
==7876== at 0x4C2BBA0: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7876== by 0x4008A7: printFile (program.c:23)
==7876== by 0x40073A: main (program.c:43)
==7876==
The world is not enought and michi is the only one who's not agree.
==7876==
==7876== HEAP SUMMARY:
==7876== in use at exit: 0 bytes in 0 blocks
==7876== total heap usage: 2 allocs, 2 frees, 621 bytes allocated
==7876==
==7876== All heap blocks were freed -- no leaks are possible
==7876==
==7876== For counts of detected and suppressed errors, rerun with: -v
==7876== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Here is the program:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char *printFile(char *fileName){
size_t length=0,size=0;
char *buffer;
FILE *file;
file = fopen (fileName , "r" );
if (file==NULL){
printf("\n");
printf("\tThe file %s does not Exists\n", fileName);
exit(1);
}
fseek (file , 0 , SEEK_END);
length = (size_t)ftell (file);
fseek (file , 0 , SEEK_SET);
buffer = malloc(length+1);
if (!buffer){
fputs ("Memory error",stderr);
exit (2);
}
size = fread (buffer,1,length+1,file);
if (size != length){
fputs ("Reading error",stderr);
exit(3);
}
fclose (file);
return buffer;
}
int main (void) {
char *fileName = "test.txt";
char *fileContent = printFile(fileName);
printf("%s",fileContent);
free(fileContent);
return 0;
}
A quick fix is to use calloc instead of malloc, because it zeros the returned bytes
So I replaced:
buffer = malloc(length+1);
with:
buffer = calloc(length,sizeof(char*));
And valgrind doesn't complain:
==7897== Memcheck, a memory error detector
==7897== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==7897== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==7897== Command: ./program
==7897==
The world is not enought and michi is the only one who's not agree.
==7897==
==7897== HEAP SUMMARY:
==7897== in use at exit: 0 bytes in 0 blocks
==7897== total heap usage: 2 allocs, 2 frees, 1,096 bytes allocated
==7897==
==7897== All heap blocks were freed -- no leaks are possible
==7897==
==7897== For counts of detected and suppressed errors, rerun with: -v
==7897== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
My question is, why does malloc produce that error and how to avoid calloc.
Do I have some codding problem here or is just malloc?
.
.
EDIT:
if I change:
size = fread (buffer,1,length+1,file);
with:
size = fread (buffer,1,length,file);
I get:
==7985== Memcheck, a memory error detector
==7985== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==7985== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==7985== Command: ./program
==7985==
==7985== Invalid read of size 1
==7985== at 0x4E864B2: vfprintf (vfprintf.c:1642)
==7985== by 0x4E8CC38: printf (printf.c:33)
==7985== by 0x40074C: main (program.c:44)
==7985== Address 0x52022f4 is 0 bytes after a block of size 68 alloc'd
==7985== at 0x4C2BBA0: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7985== by 0x4008A6: printFile (program.c:22)
==7985== by 0x40073A: main (program.c:42)
==7985==
The world is not enought and michi is the only one who's not agree.
==7985==
==7985== HEAP SUMMARY:
==7985== in use at exit: 0 bytes in 0 blocks
==7985== total heap usage: 2 allocs, 2 frees, 620 bytes allocated
==7985==
==7985== All heap blocks were freed -- no leaks are possible
==7985==
==7985== For counts of detected and suppressed errors, rerun with: -v
==7985== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
You print the file content read into your buffer but nothing can ensure that the buffer contains a NUL char, so valgrind complains because printf parse your data until NUL (jump or move depends on uninitialised value(s)). Using calloc tells valgrind that you are more precautious...
Your string must be NUL-terminated. Without it, the program has undefined behaviour, which valgrind rightfully reports.
The easiest way to NUL-terminate the string is:
size = fread (buffer,1,length,file); /* no need to specify useless extra char */
/* it will never be read */
... /* check for errors here */
buffer[length] = '\0'; /* <--- null termination */
calloc fills the entire buffer with NUL characters, but it's a waste of cycles. You only need one.
Memory obtained via malloc() is uninitialized. That's intentional. The workarounds are to use calloc() instead or to initialize that memory obtained via malloc() before you read from it. Under some circumstances you can initialize only part of it, and often you have better initial values available than all zeroes.
Your particular error is only peripherally related to that, however. You do initialize most of the buffer, via fread(), but you allocate one more byte than the file is long, and fread() does not store anything in that last byte. It looks like maybe you intended to add a '\0' terminator, but forgot. It's that last byte that valgrind complains about.
In this case, the memory-clearing performed by calloc() mostly serves no purpose, as you are about to overwrite all bytes in the buffer but one. But it does initialize that last byte, too, which turns out to save you several kinds of trouble when you fail to initialize it any other way.
I'm trying to learn a couple things (just as a hobby) and trying to learn to use Valgrind. However this doesn't seem to make sense to me. It seems Valgrind is saying that bytes are lost when I'm allocating them with calloc before I even use anything! Can someone explain what is going on here and why the second program worked? I compiled the programs in debug mode in Eclipse and ran Valgrind on the debug executable.
Here's the program:
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4
5 int main(void) {
6
7 char* origstr = calloc(37, sizeof(char*));
8 char* newsubstr = calloc(9, sizeof(char*));
9
10 origstr = "TheQuickBrownFoxJumpedOverTheLazyDog";
11
12 strncpy(newsubstr, origstr + 8, 8);
13 printf("SubString is: %s\n", newsubstr);
14
15 free(newsubstr);
16 free(origstr);
17 return 0;
18 }
And here's what Valgrind gives me:
$ valgrind --tool=memcheck --leak-check=full ./test
==25404== Memcheck, a memory error detector
==25404== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==25404== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==25404== Command: ./test
==25404==
SubString is: BrownFox
==25404== Invalid free() / delete / delete[] / realloc()
==25404== at 0x4C29E90: free (vg_replace_malloc.c:473)
==25404== by 0x400665: main (test.c:16)
==25404== Address 0x4006f8 is not stack'd, malloc'd or (recently) free'd
==25404==
==25404==
==25404== HEAP SUMMARY:
==25404== in use at exit: 296 bytes in 1 blocks
==25404== total heap usage: 2 allocs, 2 frees, 368 bytes allocated
==25404==
==25404== 296 bytes in 1 blocks are definitely lost in loss record 1 of 1
==25404== at 0x4C2AD10: calloc (vg_replace_malloc.c:623)
==25404== by 0x4005FC: main (test.c:7)
==25404==
==25404== LEAK SUMMARY:
==25404== definitely lost: 296 bytes in 1 blocks
==25404== indirectly lost: 0 bytes in 0 blocks
==25404== possibly lost: 0 bytes in 0 blocks
==25404== still reachable: 0 bytes in 0 blocks
==25404== suppressed: 0 bytes in 0 blocks
==25404==
==25404== For counts of detected and suppressed errors, rerun with: -v
==25404== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
If I remove the two free() statements, here's what Valgrind gives me:
$ valgrind --tool=memcheck --leak-check=full ./test
==25597== Memcheck, a memory error detector
==25597== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==25597== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==25597== Command: ./test
==25597==
SubString is: BrownFox
==25597==
==25597== HEAP SUMMARY:
==25597== in use at exit: 368 bytes in 2 blocks
==25597== total heap usage: 2 allocs, 0 frees, 368 bytes allocated
==25597==
==25597== 72 bytes in 1 blocks are definitely lost in loss record 1 of 2
==25597== at 0x4C2AD10: calloc (vg_replace_malloc.c:623)
==25597== by 0x4005BF: main (test.c:8)
==25597==
==25597== 296 bytes in 1 blocks are definitely lost in loss record 2 of 2
==25597== at 0x4C2AD10: calloc (vg_replace_malloc.c:623)
==25597== by 0x4005AC: main (test.c:7)
==25597==
==25597== LEAK SUMMARY:
==25597== definitely lost: 368 bytes in 2 blocks
==25597== indirectly lost: 0 bytes in 0 blocks
==25597== possibly lost: 0 bytes in 0 blocks
==25597== still reachable: 0 bytes in 0 blocks
==25597== suppressed: 0 bytes in 0 blocks
==25597==
==25597== For counts of detected and suppressed errors, rerun with: -v
==25597== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
Now, if I run this program:
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4
5 int main(void) {
6
7 char* origstr;
8 char* newsubstr = calloc(9, sizeof(char*));
9
10 origstr = "TheQuickBrownFoxJumpedOverTheLazyDog";
11
12 strncpy(newsubstr, origstr + 8, 8);
13 printf("SubString is: %s\n", newsubstr);
14
15 free(newsubstr);
16
17 return 0;
18 }
It shows everything is just fine:
$ valgrind --tool=memcheck --leak-check=full ./test
==25862== Memcheck, a memory error detector
==25862== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==25862== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==25862== Command: ./test
==25862==
SubString is: BrownFox
==25862==
==25862== HEAP SUMMARY:
==25862== in use at exit: 0 bytes in 0 blocks
==25862== total heap usage: 1 allocs, 1 frees, 72 bytes allocated
==25862==
==25862== All heap blocks were freed -- no leaks are possible
==25862==
==25862== For counts of detected and suppressed errors, rerun with: -v
==25862== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Why is it that I can't calloc (allocate) origstr and then give it something? What if I wanted to allocate that variable and in the course of the program give it part of what's in another string variable or use it to capture the result of another function that returns a string? Would I then have to handle it like I did newsubstr?
This is a bit confusing to me so can someone explain how this works so I can understand it better?
origstr = "TheQuickBrownFoxJumpedOverTheLazyDog";
By doing this you change to what origstr points to . After this origstr doesn't point to memory block allocated by calloc .
And you free memory not allocated by calloc or similar functions , thus causing error in your program.
Use strcpy to copy string to origstr -
strcpy(origstr,"TheQuickBrownFoxJumpedOverTheLazyDog");
and then you can free your pointer origstr.
By assigning the string literal to origstr you don't copy the string but just change origstrs value, thus losing the pointer to calloc. freeing origstr now causes undefined behavior.
Use strcpy or strncpy instead to really store the string on the heap. But actually dropping calloc for origstr should suffice.
Notes:
as #LeeDanielCrocker mentioned in the comments to this answer, you probably intended to allocate space for chars, not for char*s, decreasing the size of the allocated memory drastically. You should replace the sizeof(char*) with a sizeof(char) (a.k.a. 1).
Because there is a memory leak. You reassign the pointer, it's actually incorrect to free() it as you have it.
To copy the contents to the allocated pointer use strcpy()
strcpy(origstr, "TheQuickBrownFoxJumpedOverTheLazyDog");
Let's see how:
You request memory with calloc()
origstring = calloc(9, sizeof(char*))
this is wrong for multiple reasons
You are allocating space for 9 pointers, not 9 characters.
You don't really need calloc() because you will overwrite the contents immediately, use malloc().
You overwrite the pointer with a string literal
origstr = "TheQuickBrownFoxJumpedOverTheLazyDog";
now you lost reference to the pointer returned earlier by calloc() and you cannot possible free() it, you should only free() pointers return by malloc()/calloc()/realloc().
The truth is, you don't need to calloc() the oristring pointer, calloc()/malloc() are not used to allow you to assign to a pointer, but to write to the memory pointed to by the pointer, or better, to point to some memory you can read/write from/to.
I have a simple question here. I have some variable declarations as follows:
char long_name_VARA[]="TEST -- Gridded 450m daily Evapotranspiration (ET)";
int16 fill_PET_8day=32767;
Given the above valgrind complains for the char declaration as follows:
Invalid write of size 8
==21902== at 0x408166: main (main.c:253)
==21902== Location 0x7fe677840 is 0 bytes inside long_name_VARA[0]
and for the int16 declaration as follows:
==21902== Invalid write of size 2
==21902== at 0x408178: main (main.c:226)
Location 0x7fe677420 is 0 bytes inside local var "fill_PET_8day"
What am i doing wrong in my declarations here?
Also can I not declare a char array like this:
char temp_year[5]={0}
The warning messages you quoted show invalid memory accesses, which happen to hit memory areas belonging to the above two variables. The variables in question are victims of the error, not perpetrators. The variables are not to blame here. Nothing is wrong with the above declarations. Most likely these declarations are not in any way relevant here.
The perpetrators are lines at main.c:253 and main.c:226, which you haven't quoted yet. That's where your problem occurs.
A wild guess would be that you have another object declared after fill_PET_8day (an array?). When working with that other object, you overrun its memory boundary by ~10 bytes, thus clobbering fill_PET_8day and first 8 bytes of long_name_VARA. This is what valgrind is warning you about.
As mentioned, the declarations aren't the issue.
Although FYI, it may be better to declare your constant string as const...
const char* long_name_VARA = "TEST -- Gridded 450m daily Evapotranspiration (ET)";
or even...
const char* const long_name_VARA = "TEST -- Gridded 450m daily Evapotranspiration (ET)";
This prevents the string from being modified in code, (and the pointer).
When I run the following
/* test.c */
#include <stdio.h>
int main(void)
{
char s[8000000];
int x;
s[0] = '\0';
x=5;
printf("%s %d\n",s,x);
return 0;
}
with Valgrind I get
$ gcc test.c
$ valgrind ./a.out
==1828== Memcheck, a memory error detector
==1828== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==1828== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==1828== Command: ./a.out
==1828==
==1828== Warning: client switching stacks? SP change: 0xfff0002e0 --> 0xffe85f0d0
==1828== to suppress, use: --max-stackframe=8000016 or greater
==1828== Invalid write of size 1
==1828== at 0x400541: main (in /home/m/a.out)
==1828== Address 0xffe85f0d0 is on thread 1's stack
==1828== in frame #0, created by main (???)
==1828==
==1828== Invalid write of size 8
==1828== at 0x400566: main (in /home/m/a.out)
==1828== Address 0xffe85f0c8 is on thread 1's stack
==1828== in frame #0, created by main (???)
==1828==
==1828== Invalid read of size 1
==1828== at 0x4E81ED3: vfprintf (vfprintf.c:1642)
==1828== by 0x4E88038: printf (printf.c:33)
==1828== by 0x40056A: main (in /home/m/a.out)
==1828== Address 0xffe85f0d0 is on thread 1's stack
==1828== in frame #2, created by main (???)
==1828==
5
==1828== Invalid read of size 8
==1828== at 0x4E88040: printf (printf.c:37)
==1828== by 0x40056A: main (in /home/m/a.out)
==1828== Address 0xffe85f0c8 is on thread 1's stack
==1828== in frame #0, created by printf (printf.c:28)
==1828==
==1828== Warning: client switching stacks? SP change: 0xffe85f0d0 --> 0xfff0002e0
==1828== to suppress, use: --max-stackframe=8000016 or greater
==1828==
==1828== HEAP SUMMARY:
==1828== in use at exit: 0 bytes in 0 blocks
==1828== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==1828==
==1828== All heap blocks were freed -- no leaks are possible
==1828==
==1828== For counts of detected and suppressed errors, rerun with: -v
==1828== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 0 from 0)
If I give the option Valgrind warns with I get
$ valgrind --max-stackframe=10000000 ./a.out
==1845== Memcheck, a memory error detector
==1845== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==1845== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==1845== Command: ./a.out
==1845==
5
==1845==
==1845== HEAP SUMMARY:
==1845== in use at exit: 0 bytes in 0 blocks
==1845== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==1845==
==1845== All heap blocks were freed -- no leaks are possible
==1845==
==1845== For counts of detected and suppressed errors, rerun with: -v
==1845== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
So the "Invalid reads/writes" are due to the large stack variable without the proper --max-stackframe=... option.
I'm trying to backfill my knowledge of C memory management. I've come from a mostly scripting and managed background, and I want to learn more about C and C++. To that end I've been reading a few books, including one which included this example of using realloc to trim a string of whitespace:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* trim(char* phrase)
{
char* old = phrase;
char* new = phrase;
while(*old == ' ') {
old++;
}
while(*old) {
*(new++) = *(old++);
}
*new = 0;
return (char*)realloc(phrase, strlen(phrase)+1);
}
int main ()
{
char* buffer = (char*)malloc(strlen(" cat")+1);
strcpy(buffer, " cat");
printf("%s\n", trim(buffer));
free(buffer);
buffer=NULL;
return 0;
}
I dutifully copied the example, and compiled with c99 -Wall -Wpointer-arith -O3 -pedantic -march=native. I don't get any compile errors, and the app runs and does what's promised in the book, but when I run it against valgrind I get an error about invalid realloc.
==21601== Memcheck, a memory error detector
==21601== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==21601== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==21601== Command: ./trim
==21601==
==21601== Invalid free() / delete / delete[] / realloc()
==21601== at 0x402B3D8: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==21601== by 0x804844E: main (in /home/mo/programming/learning_pointers/trim)
==21601== Address 0x4202028 is 0 bytes inside a block of size 6 free'd
==21601== at 0x402C324: realloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==21601== by 0x80485A9: trim (in /home/mo/programming/learning_pointers/trim)
==21601== by 0x804842E: main (in /home/mo/programming/learning_pointers/trim)
==21601==
==21601==
==21601== HEAP SUMMARY:
==21601== in use at exit: 4 bytes in 1 blocks
==21601== total heap usage: 2 allocs, 2 frees, 10 bytes allocated
==21601==
==21601== 4 bytes in 1 blocks are definitely lost in loss record 1 of 1
==21601== at 0x402C324: realloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==21601== by 0x80485A9: trim (in /home/mo/programming/learning_pointers/trim)
==21601== by 0x804842E: main (in /home/mo/programming/learning_pointers/trim)
==21601==
==21601== LEAK SUMMARY:
==21601== definitely lost: 4 bytes in 1 blocks
==21601== indirectly lost: 0 bytes in 0 blocks
==21601== possibly lost: 0 bytes in 0 blocks
==21601== still reachable: 0 bytes in 0 blocks
==21601== suppressed: 0 bytes in 0 blocks
==21601==
==21601== For counts of detected and suppressed errors, rerun with: -v
==21601== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
So please help me understand why it's consider an invalid realloc. Is the example crap? Is there something I'm missing? I know that according to the specs, realloc expects the pointer to have been created previously by malloc, so is it because the realloc is in another function? Or is valgrind confused because they're in separate functions? I'm not a complete idiot (most days), but right now I kind of feel like one for not seeing the issue.
Thanks in advance!
You're trying to free the original pointer, not the reallocd one. You can fix it by:
buffer = trim(buffer)