I'm an expert-level C and C++ developer, with a specialty in memory management. I have experience writing memory-safe code with both the modern safe techniques and the ancient unsafe techniques. I've used malloc
and free
without killing myself. I love pointers. I've debugged more than my share of undefined behavior, and authored the canonical StackOverflow question on segfault debugging.
Any burning questions about dynamic allocation, undefined behavior, pointers, memory safety, or anything even remotely related? Ask me anything!
(My main languages are C++, C, and Python, although I also deeply grok the underlying computer science principles.)
Top comments (161)
Hello Jason! I am encountering a peculiar issue. On one system after compiling I am getting no errors with pthreads in C++. On the second I am running across a Segfault
On the other I am recieving no errors. My wild guess is that the issue might stem from the systems having different kernels:
No Problems:
cat /proc/version
Linux version 4.15.0-29-generic (buildd@lgw01-amd64-057) (gcc version 7.3.0 (Ubuntu 7.3.0-16ubuntu3)) #31-Ubuntu SMP Tue Jul 17 15:39:52 UTC 2018
Problems(SegFault):
cat /proc/version
Linux version 5.4.0-42-generic (buildd@lgw01-amd64-038) (gcc version 9.3.0 (Ubuntu 9.3.0-10ubuntu2)) #46-Ubuntu SMP Fri Jul 10 00:24:02 UTC 2020
Please let me know if any other information is needed
Every time I see "No such file or directory," the first thing I check is the path. What is the current working directory from which you're running
a.out
, and does the path../sysdeps/unix/sysv/linux/raise.c
indeed exist relative to that working directory? (Remember that..
means "parent directory".)My working path is the same as the pwd for where I am running
a.out
. In this case it would be something on the lines of/home/red/recorder
. I have no idea of where the path../sysdeps/unix/sysv/linux/raise.c
is coming from, so I would say no it does not exist. I am assuming it is a segfault of some variant when I receive a response ofdouble free or corruption (out)
andAborted (core dumped)
.I can provide a recent valgrind and or gdb bt if needed.
Yeah, that relative path is spooky.
To diagnose the double free or corrupted, you'd want to run your program through Valgrind. Meanwhile, you may need to use
gdb
to step through your program (compiled with-g
) to determine precisely when control leaves your code, onward to the abort.Alright the first block is a gdb output with a backtrace:
This is the valgrind dump (sorry for double comment; couldn't get the markdown to capture all of the code cleanly):
The most puzzling part is that I get this error on one system but not the other:
No Problems:
cat /proc/version
Linux version 4.15.0-29-generic (buildd@lgw01-amd64-057) (gcc version 7.3.0 (Ubuntu 7.3.0-16ubuntu3)) #31-Ubuntu SMP Tue Jul 17 15:39:52 UTC 2018
Problems(SegFault):
cat /proc/version
Linux version 5.4.0-42-generic (buildd@lgw01-amd64-038) (gcc version 9.3.0 (Ubuntu 9.3.0-10ubuntu2)) #46-Ubuntu SMP Fri Jul 10 00:24:02 UTC 2020
You must remember that undefined behavior is exactly that. It may appear to work, and then not work elsewhere. When it doesn't work, anything could happen, including "making demons fly out your nose". So, I'd start by going through that Valgrind output, bit by bit, and fixing each problem in your code it highlights. (The error and location of that error in your code is on the last line of each traceback block in Valgrind.)
Once your //own// code runs Valgrind pure, we can tackle any remaining weirdness.
After furious placements of
std::cout
everywhere, I discovered that my function that my thread was calling was missing its return statement. Not sure how my first system was able to bypass that issue but it arised on my second system.So, it's resolved, then?
The issue yes. My curiosity, not so much lol. It shouldn't have compiled however that behavior I believe isactually allowed, it's grandfathered in from C. Since the function returns a variable and a return is not explicitly called then the first value in the stack frame is reinterpreted as the return type and returned instead
int foo(int bar) {
int blah= 8;
blah += 4;
int zayxxy = 0;
} //returns 12
So I believe that is the reason how my first system was able to execute without any problems. However, I do not fully understand how on the second system the function was never able to terminate the function but stay stuck in a while loop and result in a segfault.
What you described, not returning a value from a non-
void
function, is actually undefined behavior in C. Therefore, once again, it is legal for the compiler to make demons fly out your nose. Anything can happen. There is no rhyme or reason.Here's C99 on it — ISO/IEC 9899:1999, section 6.9.1 paragraph 12:
One system's compiler was able to figure it out anyway, and it worked, which is legal (because anything is). The other system's compiler was not, and it had a snit.
P.S. Thanks for asking! I learned something new today, namely that the above is undefined behavior.
Glad I could help! I have definitely learned alot from this experience as well!
OK, firstly, a small nitpick, you weren't getting a segfault (SIGSEGV) but a SIGABRT
As for failing to return a value from a non-void function, you should at the very least compile with -Wall, which would have caught that. e.g
vs
And of course we also get the second warning...
I always compile with at least '-Wall -Wextra'
Hello, I am learning robotics and using ros-kinetic with gazebo7. I am trying to launch my model in gazebo but got stuck on a "segmentation fault(core dump)" error at
0x00007fffc96ac0ed in ros::NodeHandle::destruct() ()
from /opt/ros/kinetic/lib/libroscpp.so
Kindly advice
There are only two ways to debug a segmentation fault, ordinarily:
1) If you have access to the source code for ros-kinetic, you would need to compile it yourself with the
-g
flag (debug flag), and then try to use it the same way as before. Then, when the segfault occurs, you'll get a file and line number instead of the raw memory address (0x00007fffc96ac0ed
), and that will tell you where in the code the segfault is (probably) happening from.2) To get more information, you can run the code (again, compiled with -g) through a dynamic memory analyser like Valgrind. That will not only give you the file and line number where the segfault is probably occurring, but also a hint about what's going on, and possibly a longer stack track.
Given the information from (1) or (2) (and a snippet of the offending source code), I could probably help you from there.
However, if ros-kinetic is not your project, you'll be best off filing a bug report on their issue tracker.
Thanks for the advice. I did compile ros-kinetic from source but now gdb wasn't launching, I don't know why. So i reinstalled ros-kinetic from apt and ran it, gdb was working. Well I did find the source file for the function pointing to segmentation fault :-
The backtrace went till 24 frames I could provide them too if the fault is not in this part of code.
If you could help me find the error it would really boost my learning.
The stack trace would be really helpful. Also, please be sure to precede your code example with three backticks (`) on the line above the example, and three on the line below.
The stack trace is here :-
Awesome, and the code you posted earlier, is that the context for
/opt/ros/kinetic/include/realtime_tools/realtime_publisher.h:84
?Also, what is the rest of the Valgrind output? Any more details? Segfaults have many causes, so knowing which one was detected helps narrow down the problem.
The code I posted earlier is the context for frame 1&2. Actually this is the gdb output which I posted.
Well I just ran the same in valgrind and it gave:-
Speaking of any more details, I have Ubuntu xenial and trying to use my "launch file" to launch my robotic model in gazebo7(robotic simulation software) and this simulation software is giving segmentation fault on running my launch file. Since this launch file is readymade from Github I think probably there is no error in that launch file.
What do you think is causing the error based on my provided information?
o.O
Wow, I've never seen this one before. The segfault is occurring, but Valgrind doesn't seem to be catching it.
I'm curious how you're invoking Valgrind. Usually I'd just pass the executable right to it:
I invoked valgrind by specifying it as an option in the launch file itself and the same way i invoked gdb.
I am very stressed with this problem but i don't want to give up.
What do you suggest for this problem?
You know, I'd be really curious to know what would happen if you ran the launch file itself through Valgrind! If you look at the output from a moment ago, there's quite a lot that is occuring outside of Valgrind (all the lines not preceded with
==nnnnn==
(wherennnnn
is some number). The segfault at the end appears to be occuring outside of that context as well. That leads me to believe the segfault might actually be within the launch file.I just ran it through valgrind
Yikes. Could you delete that comment chain and put it in a Gist or bpaste.net or some such? It'll be easier to read.
In any case, that confirmed my suspicion; the launcher is the problem. it's not memory pure at all.
After ending the process manually I further got the output
So this was the whole output I got , sorry for uploading this in parts(character limitation).
I hope this gives something useful to track down the issue.
I apologise for making such a long comment chain.
I have now made a gist of running the launch file through valgrind in
gist.github.com/rishabh900/41fd6df...
And the above comment is the output after i terminated the process manually.
So what do you think of now?
Did you write the launcher script, or is that third-party? It's clearly written in Python, and the issue is definitely there. I just can't narrow in on the specific issue, because the memory issues are being thrown by the interpreter (e.g.
at 0x41964F: PyObject_Free (in /usr/bin/python2.7)
). That indicates that something odd has been done within the Python code, but I won't be able to diagnose this further without really fully understanding the launcher's source code, and I'm afraid I don't have time to learn it.If this is third-party code, open an issue against the launcher project, and include the above output of Valgrind.
Great to see a fellow low-level programmer on here!
I worked on a game engine written in C and was having many issues related to wrongly using the
realloc
function for dynamically allocated memory. What I did was forget to assign the reallocated memory's pointer to the return value of the function. It took me weeks before I found the underlying problem since only in some cases it would blow up. How would you go about debugging a situation like:Do you use some sort of special tools? Or just some coding standards to not let this happen?
Whenever I'm working with memory, I pair two different tools: Valgrind and Goldilocks (PawLIB).
Valgrind is a pretty ubiquitous tool on UNIX platforms which will show me all of the memory issues encountered while running, even if the undefined behavior doesn't cause any overt problems. My code isn't done until it's Valgrind-pure. However, Valgrind only monitors the execution, so...
Goldilocks is a testing framework I developed at MousePaw Media, as a part of PawLIB. You could technically use any testing framework, but the benefit to Goldilocks is that it bakes the tests into the final executable, instead of requiring an additional framework to run the tests. That way, you can start the normal executable, run each of the tests you wrote, and see which ones Valgrind complains about.
Mind you, this does require you to write a lot of comprehensive behavioral tests...but you really should be doing that anyway in production code. ;)
My approach for this specific problem is to use a compiler that warns about unused return value, such as gcc or clang. I know that stdlib.h on Linux and Mac OS X already decorates realloc() with warn_unused_result attribute.
stackoverflow.com/a/2889601
But just naively setting
p = realloc(p, ...)
is also wrong, since if the allocation fails, p would be set toNULL
but the original object is still allocated. The original pointer is lost and now a memory leak. Use reallocf() which frees the original memory if it could not be resized.That's a really nice feature, didn't know about it.
But wouldn't that mean data loss in case the memory can't be resized? Wouldn't that become an unrecoverable error?
@liulk Ha, I completely forgot to mention Clang! It does indeed have the best warnings of any compiler I've used. I almost always compile with
-Wall -Wextra -Wpedantic -Werror
; that last one (as you know, although the reader might not) causes the build to fail on any warnings.I also use
cppcheck
as part of my autoreview workflow, and resolve all linter warnings before committing to the production branch.@codevault You're right, reallocf() would just free the memory and cause data loss, so it would serve a different use case than realloc(). The more general solution would be to always use this pattern, which is more verbose:
I just find that in most of my use cases, I would end up freeing p in the error handling, so I would just use reallocf() which results in less verbose code.
I see, that makes sense. I can see myself freeing the memory most of the time when reallocation fails.
Good to note. Thanks!
I should add, I use another tool from PawLIB called IOChannel - basically, a
std::cout
wrapper - that allows me to cleanly print the address and raw memory from literally any pointer, without having to use a debugger. This can make debugging some problems infinitely easier, especially when you're contending with a Heisenbug that goes away if compiled with-g
, but appears when compiled with-O2
.Thanks for the response!
Unfortunately, I didn't find a version of Valgrind for Windows. I tried DrMemory but, after lots of struggle, it didn't give me any helpful information and dropped the ball. Do you have experience with low-level on Windows or just work exclusively on Linux since it is more convenient?
I rarely use Windows for development, as its development toolchain is almost invariably miles behind its UNIX-based counterparts.
If you're on Windows 10, I strongly recommend setting up the Windows Subsystem for Linux [WSL]. That will give you access to the Linux development environment for compiling and testing. Then, use the LLVM Clang compiler on both the WSL and the Visual Studio environments. That way, once you know it compiles and runs Valgrind-pure on WSL, you can trust that it will work on VS Clang.
RE my previous post, (which I do not see): I figured out the problem. As I suspected, when I traced the spaghetti logic, I was doing something with undefined behavior. Fixed it, and there is no problem on either instance now. Thanks for all your contribution!
Are rust and golang going to take over C and C++? In terms of desktop software/web development. Also how would you, as a C++ expert, rate these languages? Do they have potential?
I strongly believe that (virtually) all languages have their place. FORTRAN and COBOL have firmly established places in the world, and are almost certain never to lose them on account of their reliability and precedence.
C and C++ likewise have this precedence, making up a sizable chunk of our source code. It's the old "if it ain't broke, don't fix it" concept; I doubt the entire collection of software that makes up a standard Linux-based operating system will ever be rewritten from C to Rust, because most of what already exists works quite well.
That said, I think Rust and golang have a lot of potential as languages, especially Rust.
(In my personal opinion, golang is a rather hipster language, but that's based in my feelings towards it, not in anything practical; so take that with a grain of salt.)
Rust looks especially interesting in the area of error handling. I'll admit, I haven't had the time to learn it very well yet, but it's DEFINITELY high on my list!
In other words, Rust and golang will probably find established places in the programming world, but they won't be displacing C, C++, or any other established language. Every tool has its place, and a quarter inch drill bit doesn't replace a 5mm drill bit.
Rust would take over everything, but the leftist collectivist community threw a baton roue of so-called "golang" at it, and now we will all perish and return to a dark age of literal witch hunts. (Because we are all out of Moore's law)
RIP information technology and human civilization in general
LOL
Nihilist
Hello Jason!! I am having some problem of memory corruption sometimes. Could you please help me out with some possible cause. Image is attached.
This issue is not always happening but sometimes. I have some memory crunch in my arm board. Is this the cause of this undefined behavior?
dev-to-uploads.s3.amazonaws.com/up...
Yes, this is undefined behavior. The line marked
#3
indicates a double-free is occuring somewhere in your code, wherein an already-freed pointer is being freed again. The behavior of a double-free is undefined.Unfortunately, I don't have enough context here (especially in an image) to debug this for you. It looks like you're already using
valgrind
. Try compiling your own code with debug flags (-g
), and then running it through Valgrind and repeating whatever action triggers this error. The resulting stack trace should point you to the line in your code where the double-free is originating.Thank you very much for your reply.
I am unable to use valgrind on target due to very limited system memory on my embedded device. Could you please suggest any alternate approach which use low resource?
I have compiled my application with -ggdb3.
I have encounter this problem only with wide character text (std::wstring) and during the object destruction (out of scope) this corruption is happening.
Images
dev-to-uploads.s3.amazonaws.com/up...
dev-to-uploads.s3.amazonaws.com/up...
dev-to-uploads.s3.amazonaws.com/up...
dev-to-uploads.s3.amazonaws.com/up...
dev-to-uploads.s3.amazonaws.com/up...
dev-to-uploads.s3.amazonaws.com/up...
dev-to-uploads.s3.amazonaws.com/up...
Memory dump of variable from frame #6 of stack trace
dev-to-uploads.s3.amazonaws.com/up...
Could you please provide any hint?
If you have memory bugs in your code, it should also work if you compile and test it on your regular machine, even though the architecture is different. Have you tried that?
Thanks for your advice. I haven't tried to run this on regular pc. This is pretty big task but let me try this. Could you please provide any opinion to use ASAN compiled binary on target?
That might work. I haven't worked with ARM boards or microcircuits before, so I don't have much insight there.
Hi Jason,
I had a problem when mixing C and C++ code. Everything compiles just fine but when I run it I get a segfault. This happens when the code goes from C++ to C
I implemented it as follows:
include "Signature.hpp"
include
include
extern "C"{
#include "sign.h"
#include "sign.c"
#include "params.h"
#include "aes256ctr.h"
#include "aes256ctr.c"
#include "ntt.h"
#include "ntt.c"
#include "packing.h"
#include "packing.c"
#include "poly.h"
#include "poly.c"
#include "polyvec.h"
#include "polyvec.c"
#include "reduce.h"
#include "reduce.c"
#include "randombytes.h"
#include "randombytes.c"
#include "fips202.h"
#include "fips202.c"
#include "rounding.h"
#include "rounding.c"
#include "symmetric.h"
#include "symmetric-aes.c"
}
using namespace std;
// function to generate a keypair, mainly uses the c function from the Dilithium PQ scheme
void Signature::generateKeyPair(){
uint8_t* pk = getPublicKeyAddress();
uint8_t* sk = getSecretKeyAddress();
PQCLEAN_DILITHIUM5AES_CLEAN_crypto_sign_keypair(pk, sk);
cout << "I succeeded" << endl;
}
I really thought I implemented this right and I do not know what I am doing wrong. Could you help me?
For a start, you might want to wrap your code in your post above with three backticks on the line above, and three on the line below. Otherwise, it's hard to read the code. ;)
Dear Jason,
I am so sorry, this is my first time on the platform. I have used valgrind and this gives me that the segfault is caused by an invalid write of size 8. Here is my code (main function):
and this is the signature class from which the c code is called:
The PQCLEAN_DILITHIUM5AES_CLEAN_crypto_sign is a c function that was built for the NIST competition for post quantum signature schemes.
Do you know what I am doing wrong here?
More importantly, what file name and line number does it say that invalid write occurs on? (Consider posted the full output of Valgrind's error message, with traceback.)
Here is the valgrind error message. The problem happens inside another file than the two above this one although the problem can't be there because, as said above, this is code from an almost NIST standard in post quantum and has been reviewed in correctness. For completeness, here is the code:
Thank you btw for helping me!
The problem isn't always at the end of the stack trace, especially where memory management is involved. I don't think the library is at fault.
Actually, I think the problem is somewhere in
Signature.cpp
. Can you post the function in that file that includes line 73?Okay, The Signature.cpp function in which this happens is a rather short one:
PQCLEAN_DILITHIUM5AES_CLEAN_crypto_sign is the c function from the library
So I think the problem might be even further back, in main.cpp, but I cannot figure out what I am doing wrong.
The main.cpp is written as follows:
I think I found it. The problem is in main.cpp:
There are two problems here.
sizeof(*sm)
gives you the length of the value pointed to bysm
. This will not give you the length of the string, but rather the size of the first item in the string/array, being a character. In other words, the value here is1
, regardless of how long the string starting at pointersm
actually is. I'll come back to this.Even if
smLength
were correct,(size_t*) smLength;
is not going to give you the address tosmLength
for storing in the pointer. Instead, this is casting, or reinterpreting, the value, the integer1
in this case, as a pointer. But what's at pointer0x00000001
? Who knows. This is known as a wild pointer.If you look throughout your code, you'll see these same mistakes occur other times, such as with
mlen
.Don't take this as a criticism, but I'm dubious about where you learned to use pointers. This is pretty much a royal hash. If you learned this from an online tutorial, example, or article, I'd strongly recommend avoiding it in the future. (Check to make sure you didn't just misunderstand first.)
The reason for the segfault is that wild pointer in #2. It's looking in the wrong place for a value, and it isn't finding it. You're lucky it failed with a segfault; it could have read in literally anything that was stored at that address in memory, whether it was coincidentally correct, subtly wrong, or absolutely bonkers. These sorts of bugs are really unpredictable like that.
Here's the operations you're misunderstanding in this code:
Getting a Pointer
To get the address of a value, for storing in a pointer, use the
&
operator:Getting the length of a c-string (char array)
By the way...
One more pro-tip: stop using the
using namespace std;
trick. It's an antipattern; in production code, it's all too easy to lose track of what-comes-from-where. Namespaces exist to reduce that confusion, butusing namespace
negates that namespace. Most examples use it for brevity; good production code never does.Instead, explicitly spell out namespace each time:
Save yourself weeks of headaches and refactoring now. Never use
using namespace
again.Thanks for your help!
I think it works now :p
Excellent!
You will want to get into the habit of always testing your code thoroughly in Valgrind and addressing everything it complains about; even memory leaks. Undefined behavior has a habit of hiding until the most inconvient and unexpected moment. Write tests for your code (you should be doing that anyway!), and then execute those tests both outside of and within Valgrind.
Hey i write a program about TSP ant colony optimization and i get a segmentation fault when i compile and run the code, but when i debug it through gdb the program just runs flawlessly. What am i missing ?
You are dealing with what is called a Heisenbug, which is a bug, usually undefined behavior, whose behavior disappears when using debugging tools.
The first thing you should do is run the program through Valgrind (
valgrind ./myprogram
). Ideally, you should do this on the Debug version of your program (compiler flag-g
). This may provide you information on what memory errors exist in your code, and where they are in the source. Fix everything Valgrind complains about.However, if after doing that, you're still segfaulting, and even Valgrind can't pick up on any more errors, you're in for a bigger fight.
Start by reading my popular Stack Overflow Q&A Definitive List of Common Reasons for Segmentation Faults. This will attune your programming sense to what to look out for.
(I didn't include my personal favorite in that list: lambdas returning references can cause some particularly nasty undefined behavior.)
If you have an idea of when the segmentation fault occurs functionally, that can help you figure out what function(s) may be involved. If you can, try to create a Minimum Reproducable Example that has the segfault.
Print off the problem area of the code on paper. Desk check it with a red pen and a pad of paper. This means you act as the compiler, running the code mentally, and noting the value of each variable. I've caught a number of bugs this way.
If you're desperate, you can run the Release target of the program through Valgrind, although this will give you raw memory addresses instead of line numbers and file names. If you're very clever with a disassembler like Nemiver, and know how to read assembly code, you may be able to work backwards to isolate the problem. However, this is extremely hard; it will help a lot if you can do this with your Minimum Reproducible Example instead of the full program.
Good luck!
I think I kinda located the problem but i cant understand why is this happening. As you can see at the image above i for some reason decides to be whatever value it want's despite the fact that it is in a for loop.
thepracticaldev.s3.amazonaws.com/i...
This means it is reading from uninitialized memory. Common reasons for this:
You declared a variable, or dynamically allocated memory, but never initialized the memory with a value.
You are using a pointer (or reference) to either a position in memory which has already been freed (dangling pointer/reference), or which has never been allocated (wild pointer/reference). This can happen with either the heap or the stack; it's not limited to dynamic allocation.
You are exceeding the boundaries of an array or string (buffer overrun).
Have you ever worked with the Motorola 68000. I really like that CPU. In your opinion do you think assembly language is still best for super low level hardware or do you think C is on par with assembly code?
Ironically, I just added 68K Assembly to my list of languages to learn soon! I have a TI-89 calculator (Motorola 68000), and dearly want to play with it.
Up to this point, my assembly work has been largely limited to the X86 and X64 languages, in the context of Intel and AMD processors.
C is actually further up the stack than people think, and it isn't always the best choice for a given architecture. If you need total control, Assembly will always give that to you far and beyond any other language.
However, Assembly is also a pain in the butt (if an endearing one to certain classifications of nerds such as myself). If you have access to a higher level language that is reasonably optimized for that platform, and you don't need ultimate control, use it instead of Assembly.
In other words, "just because we can doesn't mean we should." If you can't make a reasoned argument for the language you're using, you're probably using the wrong language. :)
Thank you for the reply, I always value getting a second opinion. The reason I'm asking this question is because I am building a game on the Sega Genesis and I've been using A C compiler to do it.
So far it hasn't been an issue because the C compiler was built for the Sega Genesis and it has a lot of nifty features to take advantage of the hardware features such as DMA. More importantly it has sound drivers which are incredibly useful because I do not want to go around writing my own Sound Driver because I am not experienced with writing such a program.
I have recently run into a few short comings with the compiler. First and foremost being that the routines I've written in C don't seem to load as fast onto the screen as compared to Assembly.
I think I will compromise by writing my screen drawing routines in Assembly and then including them in my C code. I think that would be best for me because then I would have access to features in the C compiler as well as having access to the speed of Assembly. The problem is that I am not experienced with Assembly code. Fortunately for me, 68k assembly seems to be the easiest Assembly to learn.
By the way the C compiler I'm using is called SGDK (Sega Genesis Development Kit)
What do you think about mixing languages, is it something to be avoided?
It really depends on the languages!
There's no trouble combining C and Assembly; ultimately, C is compiled down to Assembly, at which point any Assembly code you wrote outright is just inserted in. Then, the whole thing is assembled down to binary on that particular platform.
However, you can run into varying degrees of performance issues when mixing other languages. It has to be taken on a case-by-case basis.
Bravo on making a game for Sega Genesis! Keep us posted on dev.to how that goes.
I highly recommend picking up "Game Engine Architecture" by Jason Gregory. It addresses many of the issues you're facing, and hundreds more besides, from a C and C++ perspective. He even talks about console development.
Hi Jason,
If we encounter a segfault with error code 4 or any other such error code -
localhost kernel: [139154.090095] xxxxx_process[11909]: segfault at 21 ip 00007ff5704b5254 sp 00007ff556bbbb98 error 4 in libmpi_global-release.so[7ff56c832000+6eee000]
However we see no assertions/errors and no core dumps been generated, how do we go along to debug such issues ?
Core dump configuration been verified and is correct -
Limit Soft Limit Hard Limit Units
Max core file size unlimited unlimited bytes
also the flag to generate full cores is been enabled !!!!
In almost all cases, it's very hard to debug a segfault without compiling the code in question with debug symbols (
-g
) and running it through Valgrind.Core dumps are just snapshots of the raw memory when the program crashed, and will seldom provide any clues unless you are very familiar with the entire raw memory layout of your program.
Thank you for your response !!!
The problem here is we are facing this issue specifically in our client environment, we cannot reproduce this issue in house to try compile our code using -g or use valgrind by attaching it to a process
Using valgrind would add performance overhead in customer environment, so it's not a viable option, any other means to track this live on a client environment for a particular process ?
Off the top of my head, I don't know of any practical ways to debug a segfault in production like you describe. You could use logs and observations to determine what behavior(s) precede the segfault, and use that to focus in on part of your code base.
Meanwhile, your best bet would be to try and isolate what's different about their environment versus your test environment, and try and replicate it.
In any case, this won't be easy. This roadblock you're running into is exactly why it is so often said "if we can't reproduce it, we can't fix it".
Thank you Jason for the advise..
Will see if we can try to identify a diff in production env and in general..
Logs weren't much helpful to logically conclude in this case