addr2line not show line number and filename with newer GCC - c

Problem
I'm in Linux, would like to use backtrace() function to capture segmentation fault (i.e. the SIGSEGV signal). The following C code with GCC-5.4 and addr2line can show line number and filename, but GCC 7.5 or GCC 9.3 can't get that information. How can I let addr2line show line number and file name with GCC 7.5 or 9.3?
Code
x.c:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h> /* for signal */
#include <execinfo.h> /* for backtrace() */
#define BACKTRACE_SIZE 16
void dump(void)
{
int j, nptrs;
void *buffer[BACKTRACE_SIZE];
char **strings;
nptrs = backtrace(buffer, BACKTRACE_SIZE);
printf("backtrace() returned %d addresses\n", nptrs);
strings = backtrace_symbols(buffer, nptrs);
if (strings == NULL) {
perror("backtrace_symbols");
exit(EXIT_FAILURE);
}
for (j = 0; j < nptrs; j++)
printf(" [%02d] %s\n", j, strings[j]);
free(strings);
}
void signal_handler(int signo)
{
#if 0
char buff[64] = {0x00};
sprintf(buff,"cat /proc/%d/maps", getpid());
system((const char*) buff);
#endif
printf("\n=========>>>catch signal %d <<<=========\n", signo);
printf("Dump stack start...\n");
dump();
printf("Dump stack end...\n");
signal(signo, SIG_DFL); /* restore to default signal */
raise(signo); /* resend signal */
}
int add1(int num)
{
int ret = 0x00;
int *pTemp = NULL;
*pTemp = 0x01; /* this will cause an segment fault, cause the application crash */
ret = num + *pTemp;
return ret;
}
int add(int num)
{
int ret = 0x00;
ret = add1(num);
return ret;
}
int main(int argc, char *argv[])
{
int sum = 0x00;
signal(SIGSEGV, signal_handler);
sum = add(sum);
printf(" sum = %d \n", sum);
return 0;
}
Expected and actual result
Expected:
zz#localhost$ addr2line -f -p -s -e ./a.out 0x400c46
add1 at x.c:60
Actual
zz#localhost$ addr2line -f -p -s -e ./a.out 0x55baa10213f1
?? ??:0
Steps to reproduce
gcc 5.4
compile with -g -rdynamic
zz#localhost$ gcc -g -rdynamic x.c
Execute
zz#localhost$ ./a.out
=========>>>catch signal 11 <<<=========
Dump stack start...
backtrace() returned 8 addresses
[00] ./a.out(dump+0x2e) [0x400b04]
[01] ./a.out(signal_handler+0x2e) [0x400c06]
[02] /lib/x86_64-linux-gnu/libc.so.6(+0x354c0) [0x7f38179954c0]
[03] ./a.out(add1+0x1a) [0x400c46]
[04] ./a.out(add+0x1c) [0x400c7b]
[05] ./a.out(main+0x2f) [0x400cb2]
[06] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0) [0x7f3817980840]
[07] ./a.out(_start+0x29) [0x400a09]
Dump stack end...
zsh: segmentation fault (core dumped) ./a.out
Query address for add1 function, i.e. 0x400c46 in [03] ./a.out(add1+0x1a) [0x400c46].
zz#localhost$ addr2line -f -p -s -e ./a.out 0x400c46
add1 at x.c:60
zz#localhost$
zz#localhost$ gcc --version
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
gcc 7.5/9.3
Steps are same as gcc 5.4, but with different outputs:
zz#localhost$ gcc --version
gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
zz#localhost$ gcc -g -rdynamic x.c
zz#localhost$ ./a.out
=========>>>catch signal 11 <<<=========
Dump stack start...
backtrace() returned 8 addresses
[00] ./a.out(dump+0x32) [0x55baa102129b]
[01] ./a.out(signal_handler+0x36) [0x55baa10213ab]
[02] /lib/x86_64-linux-gnu/libc.so.6(+0x46210) [0x7f4808e78210]
[03] ./a.out(add1+0x1e) [0x55baa10213f1]
[04] ./a.out(add+0x20) [0x55baa102142a]
[05] ./a.out(main+0x35) [0x55baa1021467]
[06] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf3) [0x7f4808e590b3]
[07] ./a.out(_start+0x2e) [0x55baa10211ae]
Dump stack end...
zsh: segmentation fault (core dumped) ./a.out
zz#localhost$ addr2line -f -p -s -e ./a.out 0x55baa10213f1
?? ??:0

Related

Why does pclose return prematurely?

UPDATE 1: This question has been updated to eliminate the multithreading, simplifying its scope. The original problem popened in the main thread, and pclosed the child process in a different thread. The problem being asked about is reproducible much more simply, by doing the popen and pclose in the same (main) thread.
Update 2: With help from responders at How to check libc version?, I think I've identified that the libc being used is uClibc 0.9.30.
The following code popens a script in the main thread, waits a little bit, then pcloses the child process in the same main thread. This program is cross-compiled for several cross-targets.
The executable's code:
// mybin.c
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdbool.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <unistd.h>
static FILE* logFile = NULL;
static void logInit( const char* fmt );
static void log_( const char* file, int line, const char* fmt, ... );
static void logCleanup();
#define log(fmt, ...) log_( __FILE__, __LINE__, fmt, ##__VA_ARGS__ )
int main( int argc, char* argv[] )
{
logInit( "./mybin.log" );
{
bool success = false;
FILE* f;
if ( ! (f = popen( "./myscript", "r" )) )
{
log( "popen error: %d (%s)", errno, strerror( errno ) );
goto end;
}
log( "before sleep" );
sleep( 1 );
log( "after sleep" );
pclose( f );
log( "after pclose" );
success = true;
}
end:
log( "At end" );
logCleanup();
return 0;
}
/** Initializes logging */
static void logInit( const char* file )
{
logFile = fopen( file, "a" );
}
/** Logs timestamp-prefixed, newline-suffixed printf-style text */
static void log_( const char* file, int line, const char* fmt, ... )
{
//static FILE* logOut = logFile ? logFile : stdout;
FILE* logOut = logFile ? logFile : stdout;
time_t t = time( NULL );
char fmtTime[16] = { '\0' };
struct tm stm = *(localtime( &t ));
char logStr[1024] = { '\0' };
va_list args;
va_start( args, fmt );
vsnprintf( logStr, sizeof logStr, fmt, args );
va_end( args );
strftime( fmtTime, sizeof fmtTime, "%Y%m%d_%H%M%S", &stm );
fprintf( logOut, "%s %s#%d %s\n", fmtTime, file, line, logStr );
}
/** Cleans up after logInit() */
static void logCleanup()
{
if ( logFile ) { fclose( logFile ); }
logFile = NULL;
}
The script:
#! /bin/bash
# mybin
rm -f ./myscript.log
for i in {1..10}; do echo "$(date +"%Y%m%d_%H%M%S") script is running" >> ./myscript.log; sleep 1; done
The expected behavior is that the compiled executable spawns execution of the script in a child process, waits for its completion, then exits. This is met on many cross-targets including x86, x64, and ARM. Below is an example architecture on which the expected behavior is met, compilation, and corresponding logs:
$ uname -a
Linux linuxbox 5.4.8-200.fc31.x86_64 #1 SMP Mon Jan 6 16:44:18 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
Compilation:
$ gcc --version && gcc -g ./mybin.c -lpthread -o mybin
gcc (GCC) 9.2.1 20190827 (Red Hat 9.2.1-1)
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$
mybin.log:
20200705_200950 ./mybin.c#33 before sleep
20200705_200951 ./mybin.c#35 after sleep
20200705_201000 ./mybin.c#37 after pclose
20200705_201000 ./mybin.c#44 At end
myscript.log:
20200705_200950 script is running
20200705_200951 script is running
20200705_200952 script is running
20200705_200953 script is running
20200705_200954 script is running
20200705_200955 script is running
20200705_200956 script is running
20200705_200957 script is running
20200705_200958 script is running
20200705_200959 script is running
However, on one target, an odd thing occurs: pclose returns early: after the script has started running, but well before it has completed running -- why? Below is the problem architecture on which the unexpected behavior is observed, cross-compiler flags, and corresponding logs:
$ uname -a
Linux hostname 2.6.33-arm1 #2 Wed Jul 1 23:05:25 UTC 2020 armv7ml GNU/Linux
Cross-compilation:
$ /path/to/toolchains/ARM-cortex-m3-4.4/bin/arm-uclinuxeabi-gcc --version
arm-uclinuxeabi-gcc (Sourcery G++ Lite 2010q1-189) 4.4.1
Copyright (C) 2009 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ /path/to/toolchains/ARM-cortex-m3-4.4/bin/arm-uclinuxeabi-gcc -O2 -Wall -fno-strict-aliasing -Os -D__uClinux__ -fno-strict-aliasing -mcpu=cortex-m3 -mthumb -g -ffunction-sections -fdata-sections -I/path/to/toolchains/ARM-cortex-m3-4.4/usr/include/ -Wl,--gc-sections -Wl,-elf2flt=-s -Wl,-elf2flt=8192 -I/path/to/toolchains/ARM-cortex-m3-4.4/sysroot/usr/include -I/path/to/libs/ARM-cortex-m3-4.4/usr/include/ -L/path/to/toolchains/ARM-cortex-m3-4.4/sysroot/usr/lib -lrt -L/path/to/libs/ARM-cortex-m3-4.4/usr/lib -L/path/to/libs/ARM-cortex-m3-4.4/lib -o mybin ./mybin.c -lrt -lpthread
$
mybin.log:
20200705_235632 ./mybin.c#33 before sleep
20200705_235633 ./mybin.c#35 after sleep
20200705_235633 ./mybin.c#37 after pclose
20200705_235633 ./mybin.c#44 At end
myscript.log:
20200705_235632 script is running
The gist of my question is: why does pclose return prematurely, and why only on this one cross-target?
Comments and research have me circling the notion that this is a bug in the variant/version of libc - it'd be great if someone knowledgeable on the subject could help confirm if that is the case.
Not a dup of pclose() prematurely returning in a multi-threaded environment (Solaris 11)

How to properly debug a shared library written in C?

I am currently writing a shared library that takes a UNIX username and returns a string with all of the groups that user belongs to in [group1, group2, group3...] format.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include <utmp.h>
#include <sys/types.h>
#include <grp.h>
#include <pwd.h>
int num_groups = 0;
struct passwd *pwd;
gid_t *groups;
struct group *grp;
FILE *stream;
char *buff;
size_t length;
char *printGroups(char *arg)
{
stream = open_memstream(&buff, &length);
pwd = getpwnam(arg);
getgrouplist(arg, pwd->pw_gid, groups, &num_groups);
groups = malloc(num_groups * sizeof(gid_t));
if (groups == NULL){
perror("malloc");
exit(EXIT_FAILURE);
}
getgrouplist(arg, pwd->pw_gid, groups, &num_groups);
fprintf(stream, " [");
for (int i = 0; i < num_groups; ++i){
grp = getgrgid(groups[i]);
if (i == num_groups - 1)
fprintf(stream, "%s", grp->gr_name);
else
fprintf(stream, "%s ", grp->gr_name);
}
free(groups);
fprintf(stream, "]");
fclose(stream);
return buff;
}
This is main function in my shared library that returns the string. I verified that the function is indeed correct - the same logic works in a standalone program using printf instead of open_memstream stringstream.
The library however segfaults and I can't pinpoint why. Valgrind does not output anything useful:
gcc -shared -fpic -g -Wall lib.c
valgrind ./a.out
==9916== Process terminating with default action of signal 11 (SIGSEGV)
==9916== Access not within mapped region at address 0x0
==9916== at 0x1: ???
==9916== by 0xFFF000672: ???
Same goes for gdb backtrace:
Program received signal SIGSEGV, Segmentation fault.
0x0000000000000001 in ?? () (gdb) backtrace
#0 0x0000000000000001 in ?? ()
#1 0x00007fffffffe6e9 in ?? ()
#2 0x0000000000000000 in ?? ()
I am out of ideas. Could somebody point me to a solution, ethier an error in the .so source or the reason why both Valgrind and gdb print ??? despite using the -g flag when compiling?
It looks like you're attempting to run the shared library directly. That's not how shared libraries work. They're referenced by other programs that use them.
For example, this code would use your library:
#include <stdio.h>
#include <stdlib.h>
char *printGroups(char *);
int main()
{
char *groups = printGroups("root");
printf("groups: %s\n", groups);
free(groups);
return 0;
}
If you first compile your library like this:
gcc -shared -fpic -g -Wall lib.c -o libmylib.so
Then, assuming this library lives in the same directory as the the above test code, you compile the test code like this:
gcc -g -Wall -Wextra -L. -o mytest mytest.c -lmylib
Then set an environment variable to find your library:
export LD_LIBRARY_PATH=.
You can then run the test program which will use your library.

Compilation flags in gcc to debug static variables in gdb (in AIX OS)

I need in a debug session, see and manipulate some global variables of a C program. I already tried some options of gcc, but no success until now to see (print) at least my global variables.
GDB always say: No symbol "???" in current context.
What flags shall I use in compilation with gcc to do that ?
MY SAMPLE:
#include <stdio.h>
/* Some vars to see in debug */
static long gvar = 0L;
int othervar=3;
char* onepointer=NULL;
int main() {
long lvar=gvar;
gvar = 1L;
lvar = gvar;
printf("gvar = %ld\n", gvar);
gvar = 5L;
lvar = gvar;
printf("gvar = %ld\n", gvar);
}
GDB TUI SESSION:
THE ENVIRONMENT:
OS: AIX 7
GCC: 4.8.3
GDB: 7.8.1
TRIED GCC FLAGS (in some combinations):
-g, -g3, -ggdb, -ggdb3 -O0, and others
Your compiler optimized out the gvar variable. It's allowed to do so, as it can prove this won't affect program flow, i.e. no external uses of symbol and its address is not taken.
If you need it for debugging, you can remove the static temporarily or mark it volatile or one of the other methods proposed here.
Generally, static variables (unless they are optmized out) are limited in scope to the file they're defined in. So, if you aren't stepping through that particular file, gdb's p gvar won't find it because it's out of scope.
To access static variables like gvar, regardless of context use 'x.c'::gvar to refer to it instead.
All seems to work for me (on a linux box). -O0 and -g. Do a br on main and look at locals/globals.
evaitl#evbb ~/se $ cat foo.c
#include <stdio.h>
/* Some vars to see in debug */
static long gvar = 0L;
int othervar=3;
char* onepointer=NULL;
int main() {
long lvar=gvar;
gvar = 1L;
lvar = gvar;
printf("gvar = %ld\n", gvar);
gvar = 5L;
lvar = gvar;
printf("gvar = %ld\n", gvar);
return 0;
}
evaitl#evbb ~/se $ cat Makefile
foo: foo.c
gcc -Wall -g -O0 -o $# $<
evaitl#evbb ~/se $ rm foo
evaitl#evbb ~/se $ make
gcc -Wall -g -O0 -o foo foo.c
foo.c: In function ‘main’:
foo.c:9:10: warning: variable ‘lvar’ set but not used [-Wunused-but-set-variable]
long lvar=gvar;
^
evaitl#evbb ~/se $ gdb foo
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from foo...done.
(gdb) br main
Breakpoint 1 at 0x400535: file foo.c, line 9.
(gdb) run
Starting program: /home/evaitl/se/foo
Breakpoint 1, main () at foo.c:9
9 long lvar=gvar;
(gdb) list
4 static long gvar = 0L;
5 int othervar=3;
6 char* onepointer=NULL;
7
8 int main() {
9 long lvar=gvar;
10
11 gvar = 1L;
12 lvar = gvar;
13 printf("gvar = %ld\n", gvar);
(gdb) p gvar
$1 = 0
(gdb) p lvar
$2 = 0
(gdb) p onepointer
$3 = 0x0
(gdb) p othervar
$4 = 3
(gdb) quit
A debugging session is active.
Inferior 1 [process 13890] will be killed.
Quit anyway? (y or n) y

popen()/fgets() intermittently returns incomplete output

I am experiencing a strange problem with the the popen and fgets library functions on a Linux system.
A short program demonstrating the problem is below that:
Installs a signal handler for SIGUSR1.
Creates a secondary thread to repeatedly send SIGUSR1 to the main thread.
In the main thread, repeatedly executes a very simple shell command via popen(), gets the output via fgets(), and checks to see if the output is of the expected length.
The output is unexpectedly truncated intermittently. Why?
Command-line invocation example:
$ gcc -Wall test.c -lpthread && ./a.out
iteration 0
iteration 1
iteration 2
iteration 3
iteration 4
iteration 5
unexpected length: 0
Details of my machine (the program will also compile and run with this online C compiler):
$ cat /etc/redhat-release
CentOS release 6.5 (Final)
$ uname -a
Linux localhost.localdomain 2.6.32-431.17.1.el6.x86_64 #1 SMP Wed May 7 23:32:49 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
# gcc 4.4.7
$ gcc --version
gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-4)
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# glibc 2.12
$ ldd --version
ldd (GNU libc) 2.12
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.
The program:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <pthread.h>
#include <errno.h>
void dummy_signal_handler(int signal);
void* signal_spam_task(void* arg);
void echo_and_verify_output();
char* fgets_with_retry(char *buffer, int size, FILE *stream);
static pthread_t main_thread;
/**
* Prints an error message and exits if the output is truncated, which happens
* about 5% of the time.
*
* Installing the signal handler with the SA_RESTART flag, blocking SIGUSR1
* during the call to fgets(), or sleeping for a few milliseconds after the
* call to popen() will completely prevent truncation.
*/
int main(int argc, char **argv) {
// install signal handler for SIGUSR1
struct sigaction sa, osa;
sa.sa_handler = dummy_signal_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sigaction(SIGUSR1, &sa, &osa);
// create a secondary thread to repeatedly send SIGUSR1 to main thread
main_thread = pthread_self();
pthread_t spam_thread;
pthread_create(&spam_thread, NULL, signal_spam_task, NULL);
// repeatedly execute simple shell command until output is unexpected
unsigned int i = 0;
for (;;) {
printf("iteration %u\n", i++);
echo_and_verify_output();
}
return 0;
}
void dummy_signal_handler(int signal) {}
void* signal_spam_task(void* arg) {
for (;;)
pthread_kill(main_thread, SIGUSR1);
return NULL;
}
void echo_and_verify_output() {
// run simple command
FILE* stream = popen("echo -n hello", "r");
if (!stream)
exit(1);
// count the number of characters in the output
unsigned int length = 0;
char buffer[BUFSIZ];
while (fgets_with_retry(buffer, BUFSIZ, stream) != NULL)
length += strlen(buffer);
if (ferror(stream) || pclose(stream))
exit(1);
// double-check the output
if (length != strlen("hello")) {
printf("unexpected length: %i\n", length);
exit(2);
}
}
// version of fgets() that retries on EINTR
char* fgets_with_retry(char *buffer, int size, FILE *stream) {
for (;;) {
if (fgets(buffer, size, stream))
return buffer;
if (feof(stream))
return NULL;
if (errno != EINTR)
exit(1);
clearerr(stream);
}
}
If an error occurs on a FILE stream while reading with fgets, it's undefined as to whether some bytes read are transferred to the buffer before fgets returns NULL or not (7.19.7.2 of the C99 spec). So if the SIGUSR1 signal occurs while in the fgets call and causes an EINTR, its possible that some characters may be lost from the stream.
The upshot is that you can't use stdio functions to read/write FILE objects if the underlying system calls might have recoverable error returns (such as EINTR or EAGAIN), as there's no guarantee the standard library won't lose some data from the buffer when that happens. You can claim that this is a "bug" in the standard library implementation, but it is a bug that the C standard allows.

Valgrind reporting invalid write errors

This is more focused than my previous Valgrind question; I am trying to narrow down write and read errors when parsing command-line options:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/utsname.h>
#include <sys/stat.h>
#include <string.h>
#include <locale.h>
#include <bzlib.h>
#include <zlib.h>
#include "starch.h"
#define BUFMAXLEN 1024
int main(int argc, char **argv) {
if (parseCommandLineInputs( &argc, &argv ) != 0)
exit(EXIT_FAILURE);
return 0;
}
int parseCommandLineInputs(int *argc, char ***argv) {
pid_t pid;
struct utsname uts;
char uniqTag[BUFMAXLEN];
if ((*argc == 1) || (*argc > 4)) {
printUsage();
return -1;
}
if ((pid = getpid()) < 0) {
fprintf(stderr, "\n\t[starch] - Error: Could not obtain process ID\n\n");
return -1;
}
uname( &uts );
sprintf(uniqTag, "pid%d.%s", pid, uts.nodename);
switch (*argc) {
case 2: {
if (strcmp(*argv[1], "-") != 0) {
if (fileExists(*argv[1]) != 0) { /* standard input */
...
}
return 0;
}
int fileExists(char *fn) {
struct stat buf;
int i = stat (fn, &buf);
if (i == 0)
return 0;
return -1;
}
void printUsage() {
fprintf(stderr, "my usage statement\n\n");
}
My makefile is as follows:
CC = gcc
CFLAGS = -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE=1 -DUSE_ZLIB -O3 -Wformat -Wall -pedantic -std=gnu99 -g
BIN = ../bin
all: starch
rm -rf *~
starch: starch.o
mkdir -p $(BIN) && $(CC) ${CFLAGS} starch.o -lbz2 -lz -o ${BIN}/starch
rm -rf *~
clean:
rm -rf *.o *~ ${BIN}/starch
I get the following errors when I run with valgrind:
$ valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=20 --track-fds=yes -v ../bin/starch
...
==2675== 1 errors in context 1 of 2:
==2675== Invalid read of size 8
==2675== at 0x3AB4262243: fwrite (in /lib64/libc-2.5.so)
==2675== Address 0x7fedffd68 is on thread 1's stack
==2675==
==2675==
==2675== 1 errors in context 2 of 2:
==2675== Invalid write of size 8
==2675== at 0x401AA6: parseCommandLineInputs (starch.c:217)
==2675== by 0x7FF0000AF: ???
==2675== by 0x401DFA: main (starch.c:46)
==2675== Address 0x7fedffd68 is on thread 1's stack
The first error is not telling me anything I can use, since I am not using fwrite() anywhere.
The second error is tripped up on the fprintf statement in printUsage().
Line 46 is the following line:
if (parseCommandLineInputs( &argc, &argv ) != 0)
Line 217 is the following line:
fprintf(stderr, "my usage statement\n\n");
What is wrong with my application that explains why these errors appear?
Two things that pop up to me right away:
*argv[1] is NOT the same as (*argv)[1] which is what you probably mean. Array subscripting has precedence over pointer dereferencing. This results in an invalid pointer. As many experienced programmers will tell you: "Don't try to remember the precedence of operators - if in doubt use parentheses, if not just use them anyway".
-O3 in the compiler flags is a big fat NO-NO when debugging. The compiler will mangle your code so much that it can make your life impossible. Variables can disappear completely and functions can go mysteriously away as they get inlined. If your code compiles, links and runs with -O0 (IIRC some code containing inline assembly needs -O1 with some (all?) GCC versions) use it, otherwise use -O1 at most.
There is too much missing so it is not easy to tell what is going on. I suppose that pid is pid_t?
The only thing that I then see is this one:
sprintf(uniqTag, "pid%d.%s", pid, uts.nodename);
pid_t is not necessarily an int so sprintf might be on the wrong track when parsing its arguments and messup your stack. But gcc should have have told you if you compile with -Wall, which I suppose.
Try compiling with a different compiler, clang e.g.

Resources