My code is segfaulting and I have no idea what is wrong. I've simplified it as far as I can but still can't find a problem.
C File test.c:
#include <stdlib.h>
#include <stdio.h>
struct container {
void *A[3], *B[3], *C[3], *D[3];
int x, y, z;
};
int main (int argc, char* argv[]) {
struct container *cont = malloc (sizeof cont);
FILE* fh = fopen( argv[1], "r" );
if( fh == NULL ) return 0;
fscanf(fh, "%d %d", &cont->y, &cont->z);
fclose( fh );
free( cont );
return 0;
}
Contents of test.txt
1 1
Executing and running through gdb:
$ gcc --version
gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
Copyright (C) 2013 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 -Wall -g test.c && gdb a.out
GNU gdb (GDB) 7.6.1-ubuntu
Copyright (C) 2013 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".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/dberg/ITX/Cells/test/a.out...done.
(gdb) break 26
Breakpoint 1 at 0x400739: file test.c, line 26.
(gdb) run test.txt
Starting program: /home/dberg/ITX/Cells/test/a.out test.txt
Breakpoint 1, main (argc=2, argv=0x7fffffffdf48) at test.c:26
26 fclose( fh );
(gdb) n
Program received signal SIGSEGV, Segmentation fault.
__GI___libc_free (mem=0x1) at malloc.c:2892
2892 malloc.c: No such file or directory.
(gdb)
Deleting any one of the unused struct members allows the code to execute without error. Moving any of the unused struct members to the end of the struct or decreasing the size of any 1 or all arrays also allows the code to execute successfully. The presence of the fscanf() call is also necessary for the segfault
Where is my syntax wrong and why is the size of the struct so critical to this bug?
There's a * missing in struct container *cont = malloc (sizeof cont);, you need sizeof *cont.
Bzzzt! It is not fclose that is failing, it is that you are not malloc'ing enough space to hold a (struct container) type. Which is a semantic rather than syntactic problem.
Suppose you have a file, called "stuff", containing:
1,2,3
And your program is named doit.c, and it reads this file (checking for enough arguments, checking return values from fopen and malloc, etc),
//you might want to carry a shorter name around,
typedef struct container_s
{
void *A[3], *B[3], *C[3], *D[3];
int x, y, z;
} container;
//how big is a (struct container)? depends. How big is a (void*) or an (int)?
//Suppose 32-bit, then you have 12x4+3*4=60 bytes.
//Suppose 64-bit pointer, and 32-bit integer, then you have 12x8+3*4=108 bytes.
int main (int argc, char* argv[])
{
struct container* cont;
FILE* fh = fopen( argv[1], "r" );
char* filename=NULL;
//you really should not examine argv[1] if there is no argument...
if(argc<1) {
printf("usage: stuff <filename>\n");
exit(EXIT_FAILURE);
}
filename=argv[1];
//allocate space for a (struct container_s)
if( !(cont = malloc(sizeof(struct container))) ) {
printf("error: cannot allocate container\n");
}
//check that file opens successfully,
if(!(fh=fopen(filename,"r" ))) {
printf("error: cannot open %s\n",filename);
return 0;
}
//read your vector (x,y,z),
fscanf(fh,"%d,%d,%d",&(cont->x),&(cont->y),&(cont->z));
//for fun, print the (x,y,z) coordinates,
printf("stuff(%d,%d,%d)\n",cont->x,cont->y,cont->z);
fclose(fh);
free(cont);
return 0;
}
Compile and run the above, and you get,
./doit stuff
stuff(1,2,3)
Please check the return values from library functions (fopen, malloc) and bounds check arrays (such as argv[]). Oh, and you might want to give a symbolic name for A[], B[], C[], and D[] in your container.
Related
I'm writing tests for code to handle memory on powers-of-two boundaries, and I needed a 1MB block of memory on a 1MB boundary for the tests. The code worked for small blocks, but not big ones. Eventually, I worked out it was because my supposedly aligned data was not aligned to a 1MB boundary.
(I can work around this, obviously, but I want to know what's going on.)
This code compiles without warnings, objdump says the variable is at a reasonable address, but when I run it, it's aligned on a 4K boundary, not 1M.
cat x.c ; gcc --version ; uname -a ; gcc -Wall x.c && ( objdump -x a.out | grep test_data ; ./a.out )
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct data {
char memory[1024*1024];
};
static struct data __attribute__(( aligned( 0x100000 ) )) test_data = { 0 };
int main( int argc, const char **argv )
{
printf( "test_data is actually here: %p\n", &test_data );
return 0;
}
gcc (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0
Copyright (C) 2017 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.
Linux Lubuntutu 4.15.0-72-generic #81-Ubuntu SMP Tue Nov 26 12:20:02 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
0000000000400000 l O .bss 0000000000100000 test_data
test_data is actually here: 0x5600cb9fe000
Running under gdb is interesting:
Reading symbols from ./a.out...done.
(gdb) display &test_data
1: &test_data = (struct data *) 0x400000 <test_data>
(gdb) start
Temporary breakpoint 1 at 0x659: file x.c, line 13.
Starting program: /tmp/a.out
Temporary breakpoint 1, main (argc=1, argv=0x7fffffffe038) at x.c:13
13 printf( "test_data is actually here: %p\n", &test_data );
1: &test_data = (struct data *) 0x555555954000 <test_data>
(gdb) print &test_data.memory[16]
$1 = 0x555555954010 <test_data+16> ""
(gdb) c
Continuing.
test_data is actually here: 0x555555954000
This is a loader, or possibly security module, feature.
The code has been moved in memory by a similar amount, presumably as part of address-space layout randomisation, but it is by a random number of 4k pages, which will break any coarser alignment requested by programs.
Linking the program statically stops that from happening, at least at the moment.
In the following code I get a seg.fault, I don't know why this happens since I think that I'm passing the correct parameters to fopen
Compiling :
gcc -o testloadfile testloadfile.c
Running attempts :
First attempt
./testloadfile "correctme.txt"
Second attempt
sudo ./testloadfile correctme.txt
In the same folder of testloadfile.c I have a .txt called correctme.txt
The code is the following
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
static void load_array(const char* file_name){
char *read_sentence;
char buffer[2048];
char a[100][100];
int buf_size = 2048;
FILE *fp;
int j = 0, c = 0;
printf("\nLoading data from file...\n");
printf("%s \n", file_name); //prints correctme.txt
fp = fopen(file_name,"r"); //error happens here
printf("This line won't be printed \n");
if(fp == NULL){
fprintf(stderr,"main: unable to open the file");
exit(EXIT_FAILURE);
}
read_sentence = malloc((2048+1)*sizeof(char));
read_sentence = fgets(buffer,buf_size,fp);
for(int i = 0; i < strlen(read_sentence); i++) {
a[j][c++] = read_sentence[i];
if(read_sentence[i] == ' ' || read_sentence[i] == '.' || read_sentence[i] == ',') {
j++;
c = 0;
continue;
}
}
free(read_sentence);
for(int i = 0; i < 100; i++)
printf("%s\n", a[i]);
fclose(fp);
printf("\nData loaded\n");
}
int main(int argc, char const *argv[]) {
if(argc < 2) {
printf("Usage: ordered_array_main <file_name>\n");
exit(EXIT_FAILURE);
}
load_array(argv[1]);
}
This is the mentioned folder
This is the output for gcc -g testloadfile testloadfile.c
testloadfile: In function `_fini':
(.fini+0x0): multiple definition of `_fini'
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crti.o:(.fini+0x0): first defined here
testloadfile: In function `data_start':
(.data+0x0): multiple definition of `__data_start'
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o:(.data+0x0): first defined here
testloadfile: In function `data_start':
(.data+0x8): multiple definition of `__dso_handle'
/usr/lib/gcc/x86_64-linux-gnu/5/crtbegin.o:(.data+0x0): first defined here
testloadfile:(.rodata+0x0): multiple definition of `_IO_stdin_used'
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o:(.rodata.cst4+0x0): first defined here
testloadfile: In function `_start':
(.text+0x0): multiple definition of `_start'
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o:(.text+0x0): first defined here
testloadfile: In function `_init':
(.init+0x0): multiple definition of `_init'
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crti.o:(.init+0x0): first defined here
/tmp/cc0ye2Ms.o: In function `main':
/home/zenoraiser/Scrivania/Università/Secondo Anno/Algoritmi/1718/LAB/Progetto/Esercizio2/testloadfile.c:42: multiple definition of `main'
testloadfile:(.text+0x346): first defined here
/usr/lib/gcc/x86_64-linux-gnu/5/crtend.o:(.tm_clone_table+0x0): multiple definition of `__TMC_END__'
testloadfile:(.data+0x10): first defined here
/usr/bin/ld: error in testloadfile(.eh_frame); no .eh_frame_hdr table will be created.
collect2: error: ld returned 1 exit status
Then i did ulimit -c unlimited
After that i run the program with ./testloadfile "correctme.txt"
In the end I used gdb ./bynary core, this is it's output
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 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"...
./bynary: No such file or directory.
/home/zenoraiser/Scrivania/Università/Secondo Anno/Algoritmi/1718/LAB/Progetto/Esercizio2/core: No such file or directory.
(sorry later i'll try to understand how to use the last command)
The actual seg fault is likely on this line:
free(read_sentence);
It is important to remember that printf() sends output to stdout, which is buffered. As such, things you send to it will not necessarily get printed if a seg fault occurs.
As for the seg fault itself, let's look at these lines here:
read_sentence = malloc((2048+1)*sizeof(char));
read_sentence = fgets(buffer,buf_size,fp);
It looks like you think you are allocating read_sentence and then putting the data read from fp into it (and indeed the code will act like this happened), but this is not true.
Instead, you read the data into buffer and then set read_sentence to the address of buffer.
You then do your operations and we come back to the first line I pointed out:
free(read_sentence);
This is not freeing the memory allocated in your malloc() call above, but rather buffer which is on the stack, and thus cannot be free()-ed. As an additional note, that memory you allocated originally for read_sentence, is now leaked and you won't be able to free it.
The best solution to this would be to drop read_sentence (along with the malloc() and free() pair) all together and just do your operations inside buffer instead.
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.
I usually use an input file when I write programs so that I save myself from the hassle of entering digits again and again.
Here is a program which I wrote for quicksort which some where is giving me segmentation fault
#include<stdio.h>
int partition (int *,int,int);
void quicksort (int *,int,int);
int main()
{
int i,j,a[15],choice;
int length;
printf("Entering numbers in array \n");
for(i=0;i<=14;i++)
scanf("%d",&a[i]);
printf("the sorted array is\n");
length=sizeof(a);
quicksort(a,0,length-1);
for(i=0;i<=14;i++)
printf (" %d ",a[i]);
}
int partition(int *num,int p,int r)
{
int x,j,i,temp;
x=num[r];
i=-1;
for(j=0;j<=r-1;j++)
{
if(num[j]<=x)
{
i=i+1;
temp=num[i];
num[i]=num[j];
num[j]=temp;
}
}
num[i+1]=num[r];
return i+1;
}
void quicksort (int *num,int p,int r)
{
int q;
if (p<r)
{
q=partition(num,p,r);
quicksort(num,p,q-1);
quicksort(num,q+1,r);
}
}
and here is my input file input.txt
43 12 90 3 49 108 65 21 9 8 0 71 66 81
when I I compile it as follows
cc quicksort.c
./a.out < input.txt
Now the output I am getting is
Entering numbers in array
the sorted array is
Segmentation fault
What I want to know is I use gdb frequently to debug such problems.
Is it possible that in gdb I take the input from the same file input.txt
my set of commands to use gdb is
cc -g quicksort.c
gdb
GNU gdb (GDB) 7.1-ubuntu
Copyright (C) 2010 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".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
(gdb) file a.out
(gdb) break quicksort.c:3
(gdb) run
Now what I want to know is how do I use the input file in gdb so that I do not enter again and again the array which I want to enter?
For debugging purposes, add this line to your program and comment out the first for-loop
int a[] = {43, 12, 90, 3, 49, 108, 65, 21, 9, 8, 0, 71, 66, 81};
To get maximum debug-information, compile it using
gcc -ggdb3 qs.c
and run it in gdb as
gdb -q ./a.out
and never exit your gdb session! If you recompile it, gdb will automatically notice and reload the binary; in this way you will always have your breakpoints set and everything else you crafted.
Since others have given you a hint to where the problem is, I might reveal a common macro to get the size of an static allocated array :-)
#define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0]))
As always google is your friend in such "common" use-cases.
How to load program reading stdin and taking parameters in gdb?
Input redirection in gdb (MinGW)
The reason for the seg fault maybe this line.
length=sizeof(a);
Its 60.
Your r value max should be 15. An integer is allocated 4 bytes. So your call overflows,hence the error.
I have a multithreaded (pthreads) program in which main() calls a function omp_file_open_all() and passes in a string as char* alongwith other arguments. I was debugging something using gdb and saw that gdb does not print out the string value correctly, whereas a printf inside the function prints it out correcly.
Breakpoint 1, omp_file_open_all (fd=0x423bb950, filename=0x7f605df078e0 "", mode=-16843009) at pthread_coll_file_open.c:29
29 if(omp_get_thread_num() == MASTER)
(gdb) print filename
$1 = 0x7f605df078e0 ""
So gdb shows filename as empty, whereas a printf inside the function outputs the correct value as "/tmp/test.out". The function being called (omp_file_open_all) is defined as follows (not in the same file as main()):
int omp_file_open_all (int fd, char* filename, int mode);
I cant post my program here as this is a part of a larger code thats approx. 1500 lines of code. 'filename' is a global variable and is set in main() by the main thread before newer threads are spawned.
So this is not an error, and I merely stumbled across it, but I am interested in finding out why gdb does not display the correct value.
OS: 64bit OpenSUSE,
gdb 6.8
Thanks for your help.
There might be some thing going wrong in your code. With the following code snippet, I am getting the string printed by gdb correctly.
#include <stdio.h>
#include <stdlib.h>
void checkString( char* fileName )
{
printf("%s", fileName);
}
int main()
{
char* name = "temp";
checkString(name);
return 0;
}
mahesh-babu-vattiguntas-macbook-pro:Desktop mahesh$ gdb gdb.out
GNU gdb 6.3.50-20050815 (Apple version gdb-1469) (Wed May 5 04:36:56 UTC 2010)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "x86_64-apple-darwin"...Reading symbols for shared libraries .. done
(gdb) b gdb.c:6
Breakpoint 1 at 0x100000ebc: file gdb.c, line 6.
(gdb) run gdb.out
Starting program: /Users/mahesh/Desktop/gdb.out gdb.out
Reading symbols for shared libraries +. done
Breakpoint 1, checkString (fileName=0x100000f05 "temp") at gdb.c:6
6 printf("%s", fileName);
(gdb) p fileName
$1 = 0x100000f05 "temp"
(gdb)
Try stepping forward one line (gdb "s" command) after you hit the breakpoint, then try printing it again. I've sometimes seen gdb have trouble displaying parameter values correctly when breaking at the beginning of a function.
My first guess was that there is a scoping issue, since the name of the function parameter and your global variable is identical. However, this does not seem to be the case for the following very small program:
#include <cstdio>
static char const* filename = "something";
int foobar(char const* filename)
{
printf("%s\n", filename);
}
int main(int argc, char** argv)
{
return foobar("somethingelse");
}
Compiled with:
g++ -ggdb -g3 -O0 test.cpp -o test
GDB (7.2, also on x64 but Ubuntu) gives:
Breakpoint 1, foobar (filename=0x400706 "somethingelse") at test.cpp:7
7 printf("%s\n", filename);
(gdb) p filename
$1 = 0x400706 "somethingelse"
So it's not about scoping per-se. Also, the output suggests that the parameter is indeed an empty string at execution time. Could you please provide us with the output of bt at the same time you break into the debugger? Last two stack frames are sufficient.