How to be warned about pointers to out-of-scope local variables - c

Consider the following code:
#include <stdio.h>
void badidea(int**);
int main(void) {
int* p;
badidea(&p);
printf("%d\n", *p); /* undefined behavior happens here: p points to x from badidea, which is now out of scope */
return 0;
}
void badidea(int** p) {
int x = 5;
*p = &x;
}
The intent seems to be that it will print 5, but it actually invokes undefined behavior, due to dereferencing a pointer to an out-of-scope local variable in main. How can I find instances of this problem in a codebase? Here's what I've tried so far:
Compiling with gcc -Wall -Wextra -pedantic
Compiling with clang -Weverything
Running having compiled with clang -fsanitize=undefined
Running under valgrind
None of the above produced any warnings.

Compiling first with GCC 7.2 and without -fsanitize=address and then running under Valgrind produces the following:
==25751== Conditional jump or move depends on uninitialised value(s)
==25751== at 0x4E988DA: vfprintf (vfprintf.c:1642)
==25751== by 0x4EA0F25: printf (printf.c:33)
==25751== by 0x1086E5: main (in ./a.out)
followed by other warnings.

Our CheckPointer tool can detect this using dynamic analysis, along with a wide variety of other memory access errors. The tool tracks all allocations, accesses and assignments involving explicit or implicit pointers, and complains at the earliest moment when such an access is illegal or undefined.
Saving OP's example code as "buggy.c", and running CheckPointer produces the following output (some lines removed for pedagogical reasons):
C~GCC4 CheckPointer Version 1.2.1001
Copyright (C) 2011-2016 Semantic Designs, Inc; All Rights Reserved; SD Confidential Powered by DMS (R) Software Reengineering Toolkit
Parsing source file "E:/DMS/Domains/C/GCC4/Tools/CheckPointer/Example/Source/buggy.c" using encoding CP-1252 +CRLF $^J $^M $^e -1 +8 ...
Grouping top level declarations ...
Creating object meta data initializers ...
Normalizing syntax tree ...
Instrumenting syntax tree ...
Ungrouping top level declarations ...
Writing target file "E:/DMS/Domains/C/GCC4/Tools/CheckPointer/Example/Target/buggy.c" using encoding CP-1252 +CRLF $^J $^M $^e -1 +8 ...
*** Compiling sources with memory access checking code gcc.exe -I"e:\DMS\Domains\C\GCC4\Tools\CheckPointer" -I.\Target -obuggy.exe Target\buggy.c Target\check-pointer-data-initializers.c "e:\DMS\Domains\C\GCC4\Tools\CheckPointer\check-pointer.c" "e:\DMS\Domains\C\GCC4\Tools\CheckPointer\check-pointer-splay-tree.c" "e:\DMS\Domains\C\GCC4\Tools\CheckPointer\check-pointer-wrappers.c"
*** Executing instrumented application
*** Error: CWE-465 Pointer Issue (subcategory CWE-476, CWE-587, CWE-824, or CWE-825)
Dereference of dangling pointer.
in function: main, line: 8, file E:/DMS/Domains/C/GCC4/Tools/CheckPointer/Example/Source/buggy.c
The specific type of error is reported using codes defined by the Common Weakness Enumeration standard.
NIST offers a "torture" test for Java and C errors called Juliet.
Of the 14,195 Juliet test cases that are relevant to the C language, CheckPointer detected 13257 expected memory-access errors. 908 test cases were not diagnosed, but these include ones that contain undefined behavior not related to pointer usage errors (which CheckPointer is not intended to detect), or pointer usage errors that were not exposed by the actual execution (e.g. uninitialized variable contained 0 in actual execution). [We modified some of these examples to ensure that the actual execution did not contain 0 for such variables, and afterwards CheckPointer gave an error message as expected.]
CheckPointer works with GCC and MSVisualStudio.
=======================================
#n.m. made a number of comments to various answers in this thread. He issued a kind of challenge problem where he demonstrated that valgrind can't find a bug in the following code, similar to OPs but more deeply nested:
#include <stdio.h>
void badidea(int**);
void worseidea(int**);
int main(void) {
int* p;
badidea(&p);
// printf("%d\n", *p); /* undefined behavior happens here: p points to x from badidea, which is now out of scope */
worseidea(&p);
return 0;
}
void worseidea(int **p) {
int x = 42;
printf("%d %d\n", **p, x); /* undefined behavior happens here: p points to x from badidea, which is now out of scope */
}
void badidea(int** p) {
int x = 5;
*p = &x;
}
Here's the Checkpointer run, which does diagnose the pointer problem in n.m's code:
C~GCC4 CheckPointer Version 1.2.1001
Copyright (C) 2011-2016 Semantic Designs, Inc; All Rights Reserved; SD Confidential
...
Parsing source file "C:/Users/idbaxter/AppData/Local/Temp/DMS/Domains/C/GCC4/Tools/CheckPointer/Example/Source/buggy.c" using encoding CP-1252 +CRLF $^J $^M $^e -1 +8 ...
...
Writing target file "C:/Users/idbaxter/AppData/Local/Temp/DMS/Domains/C/GCC4/Tools/CheckPointer/Example/Target/buggy.c" using encoding CP-1252 +CRLF $^J $^M $^e -1 +8 ...
*** Compiling sources with memory access checking code
gcc.exe -I"c:\DMS\Domains\C\GCC4\Tools\CheckPointer" -I.\Target -obuggy.exe Target\buggy.c Target\check-pointer-data-initializers.c "c:\DMS\Domains\C\GCC4\Tools\CheckPointer\check-
pointer.c" "c:\DMS\Domains\C\GCC4\Tools\CheckPointer\check-pointer-splay-tree.c" "c:\DMS\Domains\C\GCC4\Tools\CheckPointer\check-pointer-wrappers.c"
*** Executing instrumented application
*** Error: CWE-465 Pointer Issue (subcategory CWE-476, CWE-587, CWE-824, or CWE-825)
Dereference of dangling pointer.
in function: worseidea, line: 16, file C:/Users/idbaxter/AppData/Local/Temp/DMS/Domains/C/GCC4/Tools/CheckPointer/Example/Source/buggy.c
called in function: main, line: 10, file: C:/Users/idbaxter/AppData/Local/Temp/DMS/Domains/C/GCC4/Tools/CheckPointer/Example/Source/buggy.c

I don't think such mechanism exists in the C language, in the end pointers are simply variables holding addresses. When you give them a type it simply tells the compiler what kind of variable lies in the address space pointed by the pointer.Thus in theory pointer can hold any address values as long as it is in the defined address space.
And actually this is what makes C language really powerful. Espacially in data transferring mechanisms because you can send any type of data even the user defined structueres etc. in any order and receive/typecast in the other end easily without any concern of endiannes and such.
Though in your case , hopefully ,assuming you know your program's stack size and beginning address, You can check to see if the address content pointed by the pointer is in the area reserved for the Stack or not. Thus knowing if you are pointing to a local variable or not.
+If you must point to a local variable, you can define it as static, which place the variable outside of the stack in RAM. (You probably know it, but you know some might not.)

Related

How to force a crash in C, is dereferencing a null pointer a (fairly) portable way?

I'm writing my own test-runner for my current project. One feature (that's probably quite common with test-runners) is that every testcase is executed in a child process, so the test-runner can properly detect and report a crashing testcase.
I want to also test the test-runner itself, therefore one testcase has to force a crash. I know "crashing" is not covered by the C standard and just might happen as a result of undefined behavior. So this question is more about the behavior of real-world implementations.
My first attempt was to just dereference a null-pointer:
int c = *((int *)0);
This worked in a debug build on GNU/Linux and Windows, but failed to crash in a release build because the unused variable c was optimized out, so I added
printf("%d", c); // to prevent optimizing away the crash
and thought I was settled. However, trying my code with clang instead of gcc revealed a surprise during compilation:
[CC] obj/x86_64-pc-linux-gnu/release/src/test/test/test_s.o
src/test/test/test.c:34:13: warning: indirection of non-volatile null pointer
will be deleted, not trap [-Wnull-dereference]
int c = *((int *)0);
^~~~~~~~~~~
src/test/test/test.c:34:13: note: consider using __builtin_trap() or qualifying
pointer with 'volatile'
1 warning generated.
And indeed, the clang-compiled testcase didn't crash.
So, I followed the advice of the warning and now my testcase looks like this:
PT_TESTMETHOD(test_expected_crash)
{
PT_Test_expectCrash();
// crash intentionally
int *volatile nptr = 0;
int c = *nptr;
printf("%d", c); // to prevent optimizing away the crash
}
This solved my immediate problem, the testcase "works" (aka crashes) with both gcc and clang.
I guess because dereferencing the null pointer is undefined behavior, clang is free to compile my first code into something that doesn't crash. The volatile qualifier removes the ability to be sure at compile time that this really will dereference null.
Now my questions are:
Does this final code guarantee the null dereference actually happens at runtime?
Is dereferencing null indeed a fairly portable way for crashing on most platforms?
I wouldn't rely on that method as being robust if I were you.
Can't you use abort(), which is part of the C standard and is guaranteed to cause an abnormal program termination event?
The answer refering to abort() was great, I really didn't think of that and it's indeed a perfectly portable way of forcing an abnormal program termination.
Trying it with my code, I came across msvcrt (Microsoft's C runtime) implements abort() in a special chatty way, it outputs the following to stderr:
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
That's not so nice, at least it unnecessarily clutters the output of a complete test run. So I had a look at __builtin_trap() that's also referenced in clang's warning. It turns out this gives me exactly what I was looking for:
LLVM code generator translates __builtin_trap() to a trap instruction if it is supported by the target ISA. Otherwise, the builtin is translated into a call to abort.
It's also available in gcc starting with version 4.2.4:
This function causes the program to exit abnormally. GCC implements this function by using a target-dependent mechanism (such as intentionally executing an illegal instruction) or by calling abort.
As this does something similar to a real crash, I prefer it over a simple abort(). For the fallback, it's still an option trying to do your own illegal operation like the null pointer dereference, but just add a call to abort() in case the program somehow makes it there without crashing.
So, all in all, the solution looks like this, testing for a minimum GCC version and using the much more handy __has_builtin() macro provided by clang:
#undef HAVE_BUILTIN_TRAP
#ifdef __GNUC__
# define GCC_VERSION (__GNUC__ * 10000 \
+ __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
# if GCC_VERSION > 40203
# define HAVE_BUILTIN_TRAP
# endif
#else
# ifdef __has_builtin
# if __has_builtin(__builtin_trap)
# define HAVE_BUILTIN_TRAP
# endif
# endif
#endif
#ifdef HAVE_BUILTIN_TRAP
# define crashMe() __builtin_trap()
#else
# include <stdio.h>
# define crashMe() do { \
int *volatile iptr = 0; \
int i = *iptr; \
printf("%d", i); \
abort(); } while (0)
#endif
// [...]
PT_TESTMETHOD(test_expected_crash)
{
PT_Test_expectCrash();
// crash intentionally
crashMe();
}
you can write memory instead of reading it.
*((int *)0) = 0;
No, dereferencing a NULL pointer is not a portable way of crashing a program. It is undefined behavior, which means just that, you have no guarantees what will happen.
As it happen, for the most part under any of the three main OS's used today on desktop computers, that being MacOS, Linux and Windows NT (*) dereferencing a NULL pointer will immediately crash your program.
That said: "The worst possible result of undefined behavior is for it to do what you were expecting."
I purposely put a star beside Windows NT, because under Windows 95/98/ME, I can craft a program that has the following source:
int main()
{
int *pointer = NULL;
int i = *pointer;
return 0;
}
that will run without crashing. Compile it as a TINY mode .COM files under 16 bit DOS, and you'll be just fine.
Ditto running the same source with just about any C compiler under CP/M.
Ditto running that on some embedded systems. I've not tested it on an Arduino, but I would not want to bet either way on the outcome. I do know for certain that were a C compiler available for the 8051 systems I cut my teeth on, that program would run fine on those.
The program below should work. It might cause some collateral damage, though.
#include <string.h>
void crashme( char *str)
{
char *omg;
for(omg=strtok(str, "" ); omg ; omg=strtok(NULL, "") ) {
strcat(omg , "wtf");
}
*omg =0; // always NUL-terminate a NULL string !!!
}
int main(void)
{
char buff[20];
// crashme( "WTF" ); // works!
// crashme( NULL ); // works, too
crashme( buff ); // Maybe a bit too slow ...
return 0;
}

Weird behavior while doing C programming in eclipse [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I have not touched C for long really long time. My first language was C. But then we have been taught C++, Java and C# (in college days). Now mostly my work involve Java and groovy. And suddenly I have to do C again. I am not familiar with how industry uses C as I never was in project doing stuff in C.
I started in eclipse CDT, with MinGW on Windows 10. My new program grew big quickly. And my lack of experience was unrevealed to me. When I run, my program used to crash showing Windows dialog saying "MyProgram.exe has stopped working". Now I had no clue whats going wrong. Compilation was clean with no error, but only one warning. Now since from Java world, I was like warnings are not that fatal. So I simply just ignored it (I thats my lack of C experience). And went on debugging found the cause. Realised that the warning was indeed about the cause. Suffered mental frustation of wasting hours in debugging.
So here is code replicating issue in my original code:
1 #include "stdio.h"
2 #include "limits.h"
3
4 typedef struct TempStruct TempStruct;
5
6 struct TempStruct
7 {
8 int a;
9 TempStruct *next;
10 };
11
12 int function1(TempStruct *param)
13 {
14 return param == NULL;
15 }
16
17 int function2(TempStruct **param)
18 {
19 if(function1(param))
20 {
21 return INT_MIN;
22 }
23 *param = (*param)->next;
24 return 0;
25 }
26
27 int main()
28 {
29 TempStruct *tempStructObj = NULL;
30 function2(&tempStructObj);
31 printf("Does not reach here!!!");
32 return 0;
33 }
My C-noob eyes did not see anything wrong in it. Good that I knew how to do debugging. I got following in debugging:
In main() this is done: *tempStructObj = NULL. So, I was expecting function1() to return 1, making function2() returning from line 21.
The issue was that function1() takes TempStruct*. But on line 19, I passed it **param. So inside function1(), param wasnt NULL. So it returned false (0 I guess). So function2() did not returned from line 21. It executed (*param)->next and hence the program crashed.
My questions:
Q1. Shouldn't be such issue be reported as Error's instead of Warnings? Is there any setting which can report such potentially fatal warnings to error?
Q2. Does eclipse logs the reasons of such sudden app crash somewhere? So instead of debugging by stepping through each line, I can simply refer to the report which can possibly specify the line number which caused the crash
Q3. What is industry-standard approach to deal with such mistakes? Of course one will say dont commit the mistake. But I am asking about precautions that are taken to avoid such mistakes or auto detect them. Like above I asked about settings to make eclipse report the issue as fatal one or making crashes to generate report so that stuff can be fixed quickly instead of hours long debuggins. Do you use any better (and possibly involving smaller learning curve) alternative to (eclipse CDT + MinGW + Windows) that will provide more powerful debugging so that I can avoid such errors.
Q4. In point 1 of above diagram, what is that Error: Multiple errors reported.... This stuff occurred occasionally, but not always, say once in 5 debugging sessions. What can be the reason behind such ad hoc behavior?
Q5. In point 3 of above diagram, what is that (0x62ff2c) value of param inside function1()? If I keep signature of function1() correctly as int function1(TempStruct **param) and change inside reference correctly to *param, *param is correctly 0x0 (i.e. NULL):
Edit
This on Ideone works (with C) & prints "Does not reach here!!!". So dont know how it handled (*param)->next.
This on ideone (with C99 Strict) does gives error (not warning).
Q1. No, they are warnings as they are legit C code. It could be possible that you want such code. You can use -Werror on gcc to make warnings to errors. Also add some other flags for turning on more warnings like -Wall -Wpedantic -Wextra -Wshadow -Wconversion -Wno-sign-compare etc. This'd be a bit closer to what you're probably used to when using Java ;-)
Q2. Atleast on Linux you have coredumps, iirc Windows was minidumps. These can be loaded together with the corresponding executable into a debugger. Then you can access backtraces, values etc.
Q3.
Like above I asked about settings to make eclipse report the issue as fatal one or making crashes to generate report so that stuff can be fixed quickly instead of hours long debuggins.
Log yourself. Also there can be macros for easing this.
Do you use any better (and possibly involving smaller learning curve) alternative to (eclipse CDT + MinGW + Windows) that will provide more powerful debugging so that I can avoid such errors.
IDE is pretty irrelevant for C imho. Use Linux with native GCC instead, MinGW is nice but it can be daunting (my experience).
Ofcourse MS VSC++ can also compile C but its just for C++ compatible thus not really specific to one standard.
Q4. Well, multiple errors occured which are listed. If it's difficult to reproduce it might be a problem in your setup, this is exactly the experience I had with MinGW on Windows.
Q5. It's the address -- you have a pointer to a pointer, so the first ("outer") pointer is that address, pointing to another pointer which is NULL.
Or more verbosely:
tempStructObj is a pointer to NULL (ie. an int_ptr which holds the value 0x0.
To function2 you pass another int_ptr which holds the semi-random value/address of the automatic variable int_ptr tempStructObj is stored
Ie. you have such:
Address &tempStructObj: tempStructObj
in the RAM.
When you then call function1, you pass the value of this (not-NULL) pointer. Of course the comparison is thus always false.
You'd need to compare
*param with NULL.
Even more:
If you compile with GCC (on Linux) and use really verbose flags you get:
gcc -std=c99 -Wall -Wpedantic -Wextra -Wshadow -Wconversion -Wno-sign-compare -o main main.c
main.c: In function ‘function2’:
main.c:19:18: warning: passing argument 1 of ‘function1’ from incompatible pointer type [-Wincompatible-pointer-types]
if(function1(param))
^
main.c:12:5: note: expected ‘TempStruct * {aka struct TempStruct *}’ but argument is of type ‘TempStruct ** {aka struct TempStruct **}’
int function1(TempStruct *param)
^
So exactly the problem you had ^^
Also I'd remove the function1 altogether, it's completely unnecessary and just obfuscates the code. Also I'd use a different name for the struct and the typedef, appending the latter with a _t. Also I'd move it into one shorter piece of code.
On a side note: add a \n in the printf()-call.
Edited code:
#include <stdio.h>
#include <limits.h>
typedef struct TempStruct_s {
int a;
struct TempStruct_s *next;
} TempStruct_t;
int function(TempStruct_t **param)
{
if(!*param) {
return INT_MIN;
}
*param = (*param)->next;
return 0;
}
int main()
{
TempStruct_t *tempStructObj = NULL;
function(&tempStructObj);
printf("Does not reach here!!!\n");
return 0;
}
When you
TempStruct *tempStructObj = NULL;
function2(&tempStructObj);
you are sending into function2 the address of your variable tempStructObj (0x62ff2c). When doing
if(function1(param)){
return INT_MIN;
}
you're sending the same address (0x62ff2c). Therefore, param == NULL is false.
Q5: if you use the proper signature, as you suggest, then you check the value that tempStructObj is pointing at, which is what you want, and everything works.
The error you get about not being able to access memory 0x4 is due to your structure and wrong null checking. (*param)->next is expected work on a memory zone with an int and another pointer. However, *param is pointing at address 0x0, so the int is at address 0x0 and the next pointer is at address 0x4, hence the error.

Detect segmentation faults at compile time

Can I detect a possible segmentation fault at compile-time?
I understand the circumstance of a segmentation fault. But I am curious if GCC as a compiler has some flags to check for the basic scenarios resulting in segmentation faults.
This would help enormously to take precautions before releasing a library.
Can I detect a possible segmentation fault at compile time?
Sometimes, but no, you can't flawlessly detect these scenarios at compile time. Consider the general case in this C code:
volatile extern int mem[];
void foo (int access)
{
mem[access];
}
A compiler would be too noisy if it were to warn about this access at compile time, the code is valid C and a warning is, in general, inappropriate. Static analysis can't do anything with this code unless you have a mechanism for whole-program or link-time analysis.
An additonal optimization flag in GCC 4.8 which can sometimes catch a few out-of-bounds access in loops is `-faggressive-loop-optimizations'. This found a number of issues in the SPEC benchmark suite last year (http://blog.regehr.org/archives/918)
I understand the circumstance of segmentation fault. But i am curious if GCC as a compiler has some flags to check for the basic scenarios resulting in segmention faults.
GCC 4.8 comes with an address sanitizer which can help catch some of these run-time only issues (out of bounds/use-after-free bugs). You can use it with
-fsanitize=address.
http://gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/Debugging-Options.html#Debugging-Options
GCC 4.9 (which will be released within the next few months) comes with an undefined behaviour sanitizer and more aggressive optimization of NULL pointer paths, which might help you catch some more issues. When it comes, it will be available with -fsanitize=undefined
http://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html#Debugging-Options
Note however that neither of these are "compile-time" solutions, they both rely on instrumenting the binary and performing run-time checks.
Yes, there are ways of detecting some faults that may cause runtime errors such as segmentation faults. Those ways are called warnings. Many warnings messages are places where you have undefined behavior, and undefined behavior is often the leading cause of runtime crashes.
When I build, I always use the -Wall, -Wextra and -pedantic flags.
Other than that, there are really no good way of detecting all places that may cause segmentation faults (or other runtime errors), except strict coding guidelines, code reviews and plenty of testing.
gcc -Wall -Werror as mention by Joachim Pileborg are very good ideas. You could also use another compiler maybe. some reports more memory issues. I think you can not do a lot more at compile time.
At running time, I highly recommend Valgrind, which is a amazing tool for detecting memory issues. (don't forget to compile with the -g option)
Can I detect a possible segmentation fault at compile-time?
Yes, it is possible. Unfortunately, it is very limited what the compiler can do. Here is a buggy code example and the output from gcc and clang:
#include <stdlib.h>
int main() {
int a[4];
int x, y;
a[5]=1;
if(x)
y = 5;
x = a[y];
int* p = malloc(3*sizeof(int));
p[5] = 0;
free(p);
free(p);
}
For this buggy code, gcc -Wall -Wextra corrupt.c gives
corrupt.c: In function ‘main’:
corrupt.c:13:1: warning: control reaches end of non-void function [-Wreturn-type]
corrupt.c:6:7: warning: ‘x’ is used uninitialized in this function [-Wuninitialized]
clang catches more:
corrupt.c:5:5: warning: array index 5 is past the end of the array (which contains 4 elements) [-Warray-bounds]
a[5]=1;
^ ~
corrupt.c:3:5: note: array 'a' declared here
int a[4];
^
corrupt.c:6:8: warning: variable 'y' is used uninitialized whenever 'if' condition is false [-Wsometimes-uninitialized]
if(x)
^
corrupt.c:8:11: note: uninitialized use occurs here
x = a[y];
^
corrupt.c:6:5: note: remove the 'if' if its condition is always true
if(x)
^~~~~
corrupt.c:4:13: note: initialize the variable 'y' to silence this warning
int x, y;
^
= 0
corrupt.c:6:8: warning: variable 'x' is uninitialized when used here [-Wuninitialized]
if(x)
^
corrupt.c:4:10: note: initialize the variable 'x' to silence this warning
int x, y;
^
= 0
3 warnings generated.
I believe the above code example gives you insight what to expect. (Even though I tried, I could not get the static analyzer in clang to work.)
This would help enormously to take precautions before releasing a library.
As you can see above, it won't be an enormous help, unfortunately. I can only confirm that instrumentation is currently the best way to debug your code. Here is another code example:
#include <stdlib.h>
int main() {
int* p = malloc(3*sizeof(int));
p[5] = 0; /* line 4 */
free(p);
p[1]=42; /* line 6 */
free(p); /* line 7 */
}
Compiled as clang -O0 -fsanitize=address -g -Weverything memsen.c. (GCC 4.8 also has address santizier but I only have gcc 4.7.2.) The output:
==3476==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000f004 at pc 0x4887a7 bp 0x7fff9544be30 sp 0x7fff9544be28
WRITE of size 4 at 0x60200000f004 thread T0
#0 0x4887a6 in main /home/ali/tmp/memsen.c:4
[...]
Awesome, we know what went wrong (heap-buffer-overflow) and where (in main /home/ali/tmp/memsen.c:4). Now, I comment out line 4 and get:
==3481==ERROR: AddressSanitizer: heap-use-after-free on address 0x60200000eff4 at pc 0x4887d7 bp 0x7fff27a00d50 sp 0x7fff27a00d48
WRITE of size 4 at 0x60200000eff4 thread T0
#0 0x4887d6 in main /home/ali/tmp/memsen.c:6
[...]
Again, we see what went wrong and where. Finally, I comment out line 6.
==3486==ERROR: AddressSanitizer: attempting double-free on 0x60200000eff0 in thread T0:
#0 0x46dba1 in free /home/ali/llvm/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:65
#1 0x48878c in main /home/ali/tmp/memsen.c:7
[...]
Also caught the problem.
If your code has tests, or at least you can run your code with different inputs on your machine before releasing the library, you could probably track down a significant portion of the bugs. Unfortunately, it is not a compile-time solution and you probably don't want to release instrumented code (code compiled with -fsanitize=* flag). So if the user runs your code with an input that triggers a bug, the program will still crash with a segmentation fault.

Why is 248x248 the maximum bi dimensional array size I can declare?

I have a program problem for which I would like to declare a 256x256 array in C. Unfortunately, I each time I try to even declare an array of that size (integers) and I run my program, it terminates unexpectedly. Any suggestions? I haven't tried memory allocation since I cannot seem to understand how it works with multi-dimensional arrays (feel free to guide me through it though I am new to C). Another interesting thing to note is that I can declare a 248x248 array in C without any problems, but no larger.
dims = 256;
int majormatrix[dims][dims];
Compiled with:
gcc -msse2 -O3 -march=pentium4 -malign-double -funroll-loops -pipe -fomit-frame-pointer -W -Wall -o "SkyFall.exe" "SkyFall.c"
I am using SciTE 323 (not sure how to check GCC version).
There are three places where you can allocate an array in C:
In the automatic memory (commonly referred to as "on the stack")
In the dynamic memory (malloc/free), or
In the static memory (static keyword / global space).
Only the automatic memory has somewhat severe constraints on the amount of allocation (that is, in addition to the limits set by the operating system); dynamic and static allocations could potentially grab nearly as much space as is made available to your process by the operating system.
The simplest way to see if this is the case is to move the declaration outside your function. This would move your array to static memory. If crashes continue, they have nothing to do with the size of your array.
Unless you're running a very old machine/compiler, there's no reason that should be too large. It seems to me the problem is elsewhere. Try the following code and tell me if it works:
#include <stdio.h>
int main()
{
int ints[256][256], i, j;
i = j = 0;
while (i<256) {
while (j<256) {
ints[i][j] = i*j;
j++;
}
i++;
j = 0;
}
printf("Made it :) \n");
return 0;
}
You can't necessarily assume that "terminates unexpectedly" is necessarily directly because of "declaring a 256x256 array".
SUGGESTION:
1) Boil your code down to a simple, standalone example
2) Run it in the debugger
3) When it "terminates unexpectedly", use the debugger to get a "stack traceback" - you must identify the specific line that's failing
4) You should also look for a specific error message (if possible)
5) Post your code, the error message and your traceback
6) Be sure to tell us what platform (e.g. Centos Linux 5.5) and compiler (e.g. gcc 4.2.1) you're using, too.

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.

Resources