-
Segfault
I am receiving a Segmentation Fault on line 11. There might be something wrong with the way i am compiling it because this is the first time that i have used terminal. At any rate, the segfault is in line 11 and i have never had this problem before. Let me know what you think.
Code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct integer
{
int *digits;
int size;
};
void print(struct integer *p)
{
int i;
for (i = p->size - 1; i >= 0; i--)
printf("%d", p->digits[i]);
}
struct integer *convert_integer(char *stringInt)
{
int i;
struct integer *p = malloc(sizeof(struct integer));
p->size = strlen(stringInt);
p->digits = malloc(sizeof(int) * p->size);
for (i = 0; i < p->size; i++)
p->digits[i] = stringInt[p->size - 1 - i] - '0';
return p;
}
int isZero(struct integer *p)
{
return (p->size == 1 && p->digits[0] == 0);
}
struct integer *multiply(struct integer *p, struct integer *q)
{
int i, j, carry;
struct integer *m;
// Terminate early in special case of multiplication by zero
if (isZero(p) || isZero(q))
return convert_integer("0");
// Create struct to hold product
m = malloc(sizeof(struct integer));
m->size = p->size + q->size;
m->digits = calloc(m->size, sizeof(int));
// Perform multiplication; don't worry about addition overflows yet
for (i = 0; i < q->size; i++)
for (j = 0; j < p->size; j++)
m->digits[i + j] += q->digits[i] * p->digits[j];
// Compensate for addition overflows
for (i = carry = 0; i < m->size; i++)
{
m->digits[i] += carry;
carry = m->digits[i] / 10;
m->digits[i] = m->digits[i] % 10;
}
// Strip leading zero if it exists
if (m->digits[m->size - 1] == 0)
m->size--;
return m;
}
struct integer *destroy_integer(struct integer *p)
{
free(p->digits);
free(p);
return NULL;
}
int main(void)
{
int N, i;
char buffer[10001];
struct integer *p, *q, *m;
FILE *ifp = fopen("bigint.rft", "r");
fscanf(ifp, "%d", &N);
for (i = 1; i <= N; i++)
{
fscanf(ifp, "%s", buffer);
p = convert_integer(buffer);
fscanf(ifp, "%s", buffer);
q = convert_integer(buffer);
m = multiply(p, q);
// Problem Output
printf("Problem #%d: ", i);
print(p);
printf(" * ");
print(q);
printf(" = ");
print(m);
printf("\n");
// Memory Management
p = destroy_integer(p);
q = destroy_integer(q);
m = destroy_integer(m);
}
fclose(ifp);
return 0;
}
-
it is actually occurring in line 9, sorry
-
Why are you so sure it's those lines? Think about it. Line 11 is just the line describing a function. Line 9 is the closing curly brace of a struct definition.
A seg fault happens when your program tries to access memory it doesn't have access to (e.g. read an invalid address, write to read-only memory, etc). That means that the offending line of code must actually be runnable code, i.e. a line of code that does something. Lines 11 and 9 do not do anything themselves.
You should also learn to use a debugger, it's perhaps the most valuable tool for a programmer. It will help you track down seg faults and other problems. Take a look (gdb is my debugging program, ./foo is your program):
Code:
$ gdb ./foo
GNU gdb (GDB) Fedora (7.3-43.fc15)
Copyright (C) 2011 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 "i686-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/cagarvin/sandbox/cprogramming/foo...done.
(gdb) r
Starting program: /home/cagarvin/sandbox/cprogramming/foo
[Thread debugging using libthread_db enabled]
Program received signal SIGSEGV, Segmentation fault.
0x4d4d00fe in __isoc99_fscanf () from /lib/libc.so.6
Missing separate debuginfos, use: debuginfo-install cyrus-sasl-lib-2.1.23-18.fc15.i686 glibc-2.14.1-6.i686 keyutils-libs-1.2-7.fc15.i686 krb5-libs-1.9.3-2.fc15.i686 libcom_err-1.41.14-2.fc15.i686 libselinux-2.0.99-4.fc15.i686 nspr-4.9-2.fc15.i686 nss-3.13.4-2.fc15.i686 nss-softokn-freebl-3.13.4-1.fc15.i686 nss-util-3.13.4-2.fc15.i686 openldap-2.4.24-3.fc15.i686 openssl-1.0.0j-1.fc15.i686 postgresql-libs-9.0.8-1.fc15.i686 zlib-1.2.5-3.fc15.i686
(gdb) bt
#0 0x4d4d00fe in __isoc99_fscanf () from /lib/libc.so.6
#1 0x0804897b in main () at foo.c:89
(gdb) fr 1
#1 0x0804897b in main () at foo.c:89
89 fscanf(ifp, "%d", &N);
(gdb) p ifp
$1 = (FILE *) 0x0
That loads your program in the debugger.
That runs your program.
That gives a backtrace, i.e. a list of which functions are calling which functions at the point of the crash.
That is your seg fault.
That is the offending line, line 89.
That takes me to stack frame #1, the main() function.
That prints the value of ifp, which is NULL (0x0).
Now, line 89
Code:
fscanf(ifp, "%d", &N);
Something there is not right. In my case, it turns out ifp is NULL, because I don't have bigint.rft and so fopen failed. You need to check the return value of all IO functions. If they fail, print a useful error (try the perror() function, or look into errno and strerror()). Then, act accordingly, either return from your function with an error, quit the program, or take some other measure.
Your problem may be slightly different, since you may have that file. But if you used to use an IDE and now you're compiling/running from a terminal, you may be "missing" the file too. More likely, the file is not located in the current directory when you run the program, something that may be setup differently in the IDE.
-
thanks i need to look into it a bit more but this reply has been helpful
-
here is my output
(gdb) r
Starting program: /Users/claytoncuteri/Desktop/bigint
Reading symbols for shared libraries +............................. done
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000068
0x00007fff94f12781 in __svfscanf_l ()
(gdb) bt
#0 0x00007fff94f12781 in __svfscanf_l ()
#1 0x00007fff94f0e98d in fscanf ()
#2 0x0000000100000b89 in main ()
(gdb) fr1
Undefined command: "fr1". Try "help".
(gdb) fr 1
#1 0x00007fff94f0e98d in fscanf ()
(gdb) p ifp
No symbol table is loaded. Use the "file" command.
(gdb)
-
Perhaps you should test if ifp == NULL ?
-
> (gdb) fr 1
> #1 0x00007fff94f0e98d in fscanf ()
You want to adjust your frame command to get to main, if you want to see the line of code in main which called fscanf, and thus see the value of ifp.