Where is my segmentation fault? [closed] - c

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I've got code that compiles well enough, but when I try to run it, I get a segmentation fault and I can't figure out what's wrong.
The point of the program is to piece together the text of fragmentet ascii art files of varying dimensions and number of fragments.
The fragments are named part_xx-yy where xx is from 00 to 11 and yy is from 00 to 05.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void)
{
int width;
int height;
int xPieces;
int yPieces;
int xTens=0;
int xOnes=0;
int yTens=0;
int yOnes=0;
printf("Fragment width: ");
scanf("%d", &width);
printf("Fragment height: ");
scanf("%d", &height);
printf("Number of fragments on x axis: ");
scanf("%d", &xPieces);
printf("Number of fragments on y axis: ");
scanf("%d", &yPieces);
printf("wtf0");
char *line=malloc(sizeof(width) * sizeof(char));
printf("wtf1");
char array[xPieces][yPieces][height][width];
printf("wtf2");
char fileName[50];
printf("wtf3");
for(int x = 0; x<xPieces;)
{
printf("%d", x);
for(int y = 0; y<yPieces;)
{
printf("%d", y);
if(xOnes>=10)
{
xOnes=0;
xTens++;
}
if(yOnes>=10)
{
yOnes=0;
yTens++;
}
snprintf(fileName, sizeof fileName, "part_%i%i-%i%i", xTens, xOnes, yTens, yOnes);
FILE *file=fopen(fileName, "r");
char buffer[(width) * (height)];
fread(buffer, 1, (width) * (height), file);
for(int i = 0; i<height; i++)
{
printf("%d", i);
for(int j = 0; j<width; j++)
{
printf("%d", j);
array[x][y][i][j] = buffer[j + (i * (width))];
}
}
fclose(file);
y++;
yOnes++;
}
x++;
xOnes++;
}
FILE *newFile=fopen("newFile", "w");
for(int y = 0; y<yPieces; y++)
{
for(int i = 0; i<height; i++)
{
for(int x = 0; x<xPieces; x++)
{
for(int j = 0; j<width; j++)
{
fwrite(&array[x][y][i][j], 1, 1, newFile);
}
}
}
}
fclose(newFile);
free(line);
}
I figured out how to use the debugger, and that indicated there was something wrong with fread(), which I think was caused by my fileName array, but I changed a few things and now all I get from the debugger is this:
Program received signal SIGSEGV, Segmentation fault.
0x0018d68c in fread () from /lib/tls/i686/cmov/libc.so.6
I thought perhaps fread() tried to read into a too small buffer, so I increased the buffer to 10000 (which SHOULD be dramatic overkill), but alas, to no avail.
I have researched quite a bit now, struggling with this problem for a couple of hours, but still have no idea how to go further from here as what I find of similar problems doesn't make much sense to me or isn't similar enough.
I think at this point I need someone else to look at my code, so any help will be greatly appreciated.
.
.
Update: I've updated my code with a few changes, and now I get a segmentation fault here instead:
Program received signal SIGSEGV, Segmentation fault.
0x08049058 in main () at innlev3.c:50
50 *array[x][y][i][j] = buffer[j + (i * (*width))];
I thought this part was pretty good... What have I done wrong, here?
Update 2: Code updated again. I've found something I think is very strange... Neither of those printf's after my scanf's work... Aand I'm back to the good old fread() segmentation fault. I guess it's a good thing I didn't make a new question out of this... :P
Program received signal SIGSEGV, Segmentation fault.
0x0018d68c in fread () from /lib/tls/i686/cmov/libc.so.6
(gdb) backtrace
#0 0x0018d68c in fread () from /lib/tls/i686/cmov/libc.so.6
#1 0x08048fc6 in main ()

I'm guessing file is NULL, probably indicating that *fileName doesn't exist.
Note that statements like this:
fileName[5] = "%i",xTens;
don't do what you probably expected. That statement is equivalent to:
fileName[5] = xTens;
And that should have given you a compiler warning, since you're assigning an int to a char*.
Instead, you probably meant to use snprintf to use printf-style formatting to construct the filename.
char filename[50];
snprintf(filename, sizeof filename, "part_%i%i-%i%", xTens, xOnes, yTens, yOnes);
FILE *file=fopen(fileName, "r");
For your second crash: You have an extra layer of pointers that you don't need on array. Declare it as char array... and remove the * when you access it. As it stands now, you've told the compiler that the elements will be pointers, but you haven't made them point anywhere, and then you asked the compiler to go look where they're pointing using *. Boom!
Your final use of array then needs to make a pointer to each character to pass to fwrite. You'd do that with the & operator, called "address-of", used like &array....
The address-of operator is the opposite of *. Once you have the program working, you can use & other places to simplify your code. For example, instead of declaring int *width and allocating it off the heap using malloc, you can remove the * everywhere and pass &width to scanf.
Since we're back to the fread segfault: Check the return value of fopen before you use it. If it's NULL, print an error message.
if(file == NULL)
{
printf("can't open %s\n", fileName);
exit(1);
}
That will probably tell you what's wrong. However, this isn't debugging code. You should generally check for error returns from the functions you call.

You aren't setting *width to anything before you use it.
You want to do your allocation after you have read the sizes.
printf("fragment width: ");
scanf("%i", width);
printf("fragment height: ");
scanf("%i", height);
char *line=malloc(sizeof(*width) * sizeof(char));
Also, this isn't doing what you think it is:
FILE *file=fopen(*fileName, "r");
It is going to open a file called "p".
And this doesn't do what you think it does either:
fileName[5] = "%i",xTens;
I think you are thinking of python.

+1 for learning to use the debugger :) You're not checking the return value of "fopen". What value of file is being passed to fread?

If you run gdb and backtrace you see this:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7a8a724 in fread () from /lib/x86_64-linux-gnu/libc.so.6
(gdb) backtrace
#0 0x00007ffff7a8a724 in fread () from /lib/x86_64-linux-gnu/libc.so.6
#1 0x0000000000400ad1 in main ()
it means that you are crashing in fread. Your file variable in fread() seems to be incorrect.

Related

Segmentation fault

#include <stdio.h>
int main(void)
{
/* an array with 5 rows and 2 columns*/
char* a[5][2];
int y, p;
for(y = 0; y < 5; y++)
{
for(p = 0; p < 2; p++)
{
scanf("%s", a[y][p]);
}
}
int i, j;
/* output each array element's value */
for ( i = 0; i < 5; i++ )
{
for ( j = 0; j < 2; j++ )
{
printf("a[%d][%d] = %s\n", i,j, a[i][j] );
}
}
return 0;
}
I've been getting a Segmentation fault as an output of this program after inserting 2 strings. Can anyone tell me what's wrong with my code?
Problem:
You're declaring 10 uninitialized pointers here:
char* a[5][2];
And then trying to fill them with data:
scanf("%s", a[y][p]);
This is wrong. You need to allocate memory before copying data.
Solution:
I would do this in a more sexy way, but the quick solution would be:
#define MAX_LEN 100
char a[5][2][MAX_LEN];
/* ... */
scanf("%s", a[y][p][0]);
Just a hint on helping troubleshoot. Hope this will help the future readers who are new to pointers.
A better way to troubleshoot a segmentation fault is to run it with a debugger like gdb.
e.g
Compile your program with gdb (You need gdb installed on your host)
gcc -ggdb Test.c -o Test
Then run it with gdb
gdb ./Test
In your case, you will see an output like this. It'll go to the gdb prompt.
Then type run or r, it will run the program. Then it asks for an input. Type your input value. Then the segmentation fault occurs. Now you can see your backtrace by typing backtrace or bt. You can see which line causes your crash. You can see the code by list. You can go to any line by typeing list <line>. Go through a GDB Guide to find out more commands.
It tries to access a pointer, probably invalid that's why it crashes. Then find out why it's invalid. Probably you didn't initialize it or didn't allocate memory. So the easiest fix would be to declare it as an array (rather than a pointer array) like #Andrewjs mentioned in his answer.
Reading symbols from /tmp/Examples/Test...done.
(gdb) run
Starting program: /tmp/Examples/Test
for 1
for 2
10
Program received signal SIGSEGV, Segmentation fault.
0x005c5c3d in _IO_vfscanf_internal (s=0x6d1420, format=0x804867e "%s", argptr=0xbfffe984 "\020\204\004\b", errp=0x0) at vfscanf.c:840
840 *str++ = c;
(gdb) backtrace
#0 0x005c5c3d in _IO_vfscanf_internal (s=0x6d1420, format=0x804867e "%s", argptr=0xbfffe984 "\020\204\004\b", errp=0x0) at vfscanf.c:840
#1 0x005cebbb in __scanf (format=0x804867e "%s") at scanf.c:35
#2 0x0804850d in main () at Test.c:16 <-- Your program's last call
(gdb) list
835 }
836 #else
837 /* This is easy. */
838 if (!(flags & SUPPRESS))
839 {
840 *str++ = c; <-- Crash point
841 if ((flags & MALLOC)
842 && (char *) str == *strptr + strsize)
843 {
844 /* Enlarge the buffer. */
(gdb)
For advance debugging of applications This may help

Segmentation on on vprintf.c

I'm a second year cs student, still not nearly as proficient at programming as I would like to be. We're working with OS161 in C this year.
To the problem, I'm supposed to write a C program that can take command like arguments and echo them back. Ok, no problem. I've done this in other languages before. Here's the code I tried:
#include <stdio.h>
int main (int argc, char *argv[]) {
int i = 0;
printf("\ncmdline args count=%s", argc);
/* First argument is executable name only */
printf("\nexe name=%s", argv[0]);
for (i=1; i< argc; i++) {
printf("\narg%d=%s", i, argv[i]);
}
printf("\n");
return 0;
}
This compiles just fine with gcc, but when I run it, I get Segmentation Fault. I run it with gdb, and this is what I get:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7abc493 in _IO_vfprintf_internal (s=0x7ffff7dd97a0, format=<value optimized out>,
ap=0x7fffffffe3f0) at vfprintf.c:1623
1623 vfprintf.c: No such file or directory.
in vfprintf.c
When I comment out the printf statements, it runs, but obviously then won't do what I need it to. As far as I can tell, it is the printf statements that are the problem, but why? I looked it up and I included the right header. It's hard for me to imagine that there is actually something wrong with vfprintf.c, since this all takes place on my school's VM that I ssh into. If anyone could throw me a bone, I'd really appreciate it. Thanks!
Edit, as you can see, I have the wrong conversion specifier. That was the whole problem.
argc is an integer, but you told printf to use the format %s.
printf("\ncmdline args count=%s", argc);
Because you used %s, printf treats the value of argc as a memory address from which it tries to fetch the characters in the string, which resulted in the segmentation fault.
Change the format to %d:
printf("\ncmdline args count=%d", argc);

Why is this C for-loop not working properly?

int main()
{
int t, i;
int *nums;
scanf("%d", &t);
nums = malloc(t * sizeof(int));
for(i = 0; i < t; i++)
{
scanf("%d", &nums[i]);
}
printf("hey");
}
For some reason, it hangs, waiting for more input! Any ideas?
This code is correct, except for the fact that you're not freeing your memory (not a big issue for this simple code) and you're not checking scanf for errors, which may be the cause of your problem.
A better implementation with error checking and correct memory handling is described below:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int t, i, ret;
int *nums;
ret = scanf("%d", &t);
if(ret != 1)
{
/* something wrong */
}
nums = malloc(t * sizeof(int));
if(nums==NULL)
{
/* memory error */
}
for(i = 0; i < t; i++)
{
ret = scanf("%d", &nums[i]);
if(ret != 1)
{
/* something wrong */
}
}
free(nums);
printf("hey");
return 0;
}
Just a guess here...
But I'm guessing you ran it and entered :
4
1234
For example, you put in 4 and then 1234 and it hangs. Well, that would be because 1234 is the first number and not 4 distinct numbers so its waiting for the second number. You have to press enter or some such delimiter between each number.
Try this set of inputs instead:
4
1234
29
4
5
You should get :
hey
Pro grammatically, you should be checking return values from your function calls. Make sure malloc didn't return zero. Make sure scanf returns the number of inputs you expected to read. Add in printouts to make sure the values it read in are what you expected/wanted to read in.
EDIT :
Guessing you have a typo in the program which isn't displayed here. such as :
scanf("%s", &t);
Or you are getting the 'hey' and just not seeing it.
[ov#MARVIN sotest]$ ./a.out
5 5 4 3 23 1
hey[ov#MARVIN sotest]$
See the 'hey' is sort of hidden in my prompt because you are missing the '\n' new line in the printout?
Remember to flush when you are done.
In chat, OP's comments "No... BTW, if I add a printf in the loop that prints the current input, it prints everything except from the last one...". This hinted that the issue was on the final output.
The following sends data out to be printed. But stdout is typically buffered. Actual output may not occur until sometime later. Output is flushed when 1) output contains an end-of-line '\n', 2) fflush() is called 3) the program ends. I am surprised output did not appear when the program ended, but possibly OP's true code differs from the post.
printf("hey");
Change to
printf("hey\n");
Or #Cool Guy
printf("hey");
fflush(stdout);
BTW: This is also hinted in #Diversity answer.
Note: Always a good idea to check the result of scanf()
// scanf("%d", &t)
if (1 != scanf("%d", &t)) Handle_BadInput_or_EOF();

Segmentation fault in fscanf() function

I am writing some code for a C wordsearch program and, while compiling one of the files, i get segmentation fault on fscanf function but i don't know where the error is.
I already searched for the answer and i understood that on integer variables I must initialize the value of them (and I already done it) and that i must refer the types inside fscanf() with '&' (done it too).
Here is the code( in the main() function):
int i;
int nl = 0;
int nc = 0;
int a, b, d;
char mat[1000][1000];//character matrix for wordsearch letters
int x[1000], y[1000];
int l, c, n;
printf("Chose the wordsearch you want to use.\n For example: t01.in, t02.in, t03.in, t04.in, (...),t30.in\n");
char wordsearch_file[8];
fgets(wordsearch_file,8,stdin);//user enters f.e. 't01.in'
FILE *stream;
char buffer[1024];
sprintf(buffer, "home/adminuser/Desktop/LA/ETAPA2/sopas/%s", wordsearch_file);
stream = fopen(buffer,"r");
if((fscanf (stream,"%d%d", &nl, &nc)) > 0){ // SEG. FAULT happens here
for(l = 0; l < nl; l++) {
for(c = 0; c < nc; c++)
mat[l][c] = fgetc(stream) != EOF;
fgetc(stream);
}
}
I wanted 'nl' (number of lines) to read 3 and 'nc' (number os columns) to read the other 3.
The 't01.in' file:
3 3
SIA
ORR
EDI
Anytime you open an external resource (file, database, socket), or make any system call whatsoever, you always check for a valid stream or return code.
The first thing you should do is add a check for stream instead of blindly calling fscanf(stream,...) without knowing if the fopen() call succeeded.
Then decide why fopen() failed. I suggest printing out the filenamne, or checking that it exists, and/or using perror() to print the system error. perror() will tell you exactly what is wrong, and if I had to guess, it would be as #BLUEPIXY mentioned, a newline in the filename.
stream = fopen(buffer,"r");
if(!stream) {
perror("what the problem: ");
}
Lastly, learn how to use the debugger to analyze the core file. If you aren't getting a core dump, set your ulimit correctly. From memory, you want "ulimit -c unlimited". Find out your current ulimits by typing simply "ulimit" at the shell prompt. Then re-run your crashing program. Once you get a core file, run GNU debugger on it.
gdb program.exe core

fopen Segfault error on large files

Hello everyone I'm new to C but I've recently been getting a weird segfault error with my fopen.
FILE* thefile = fopen(argv[1],"r");
The problem I've been having is that this code works on other smaller text files, but when I try with a file around 400MB it will give a sefault error. I've even tried hardcoding the filename but that doesn't work either. Could there be a problem in the rest of the code causing the segfault on this line?(doubt it but would like to know if its possible. It's just really odd that no errors come up for a small text file, but a large text file does get errors.
Thanks!
EDIT* didn't want to bog this down with too much but heres my code
int main(int argc, char *argv[])
{
if(argc != 3)
{
printf("[ERROR] Invalid number of arguments. Please pass 2 arguments, input_bound_file (column 1:probe, columne 2,...: samples) and desired_output_file_name");
exit(2);
}
int i,j;
rankAvg= g_hash_table_new(g_direct_hash, g_direct_equal);
rankCnt= g_hash_table_new(g_direct_hash, g_direct_equal);
table = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
getCounts(argv[1]);
printf("NC=: %i nR =: %i",nC,nR);
double srcMat[nR][nC];
int rankMat[nR][nC];
double normMat[nR][nC];
int sorts[nR][nC];
char line[100];
FILE* thefile = fopen(argv[1],"r");
printf("%s\n", strerror(errno));
FILE* output = fopen(argv[2],"w");
char* rownames[100];
i=0;j = 1;
int processedProbeNumber = 0;
int previousStamp = 0;
fgets(line,sizeof(line),thefile); //read file
while(fgets(line,sizeof(line),thefile) != NULL)
{
cleanSpace(line); //creates only one space between entries
char dest[100];
int len = strlen(line);
for(i = 0; i < len; i++)
{
if(line[i] == ' ') //read in rownames
{
rownames[j] = strncpy(dest, line, i);
dest[i] = '\0';
break;
}
}
char* token = strtok(line, " ");
token = strtok(NULL, " ");
i=1;
while(token!=NULL) //put words into array
{
rankMat[j][i]= abs(atof(token));
srcMat[j][i] = abs(atof(token));
token = strtok(NULL, " ");
i++;
}
// set the first column as a row id
j++;
processedProbeNumber++;
if( (processedProbeNumber-previousStamp) >= 10000)
{
previousStamp = processedProbeNumber;
printf("\tnumber of loaded lines = %i",processedProbeNumber);
}
}
printf("\ttotal number of loaded lines = %i \n",processedProbeNumber);
fclose(thefile);
How do you know that fopen is seg faulting? If you're simply sprinkling printf in the code, there's a chance the standard output isn't sent to the console before the error occurs. Obviously, if you're using a debugger you will know exactly where the segfault occured.
Looking at your code, nR and nC aren't defined so I don't know how big rankMat and srcMat are, but two thoughts crossed my mind while looking at your code:
You don't check i and j to ensure that they don't exceed nR and nC
If nR and nC are sufficiently large, that may mean you're using a very large amount of memory on the stack (srcMat, rankMat, normMat, and sorts are all huge). I don't know what environemnt you're running in, but some systems my not be able to handle huge stacks (Linux, Windows, etc. should be fine, but I do a lot of embedded work). I normally allocate very large structures in the heap (using malloc).
Generally files 2GB (2**31) or larger are the ones you can expect to get this on. This is because you are starting to run out of space in a 32-bit integer for things like file indices, and one bit is typically taken up for directions in relative offsets.
Supposedly on Linux you can get around this issue by using the following macro defintion:
#define _FILE_OFFSET_BITS 64
Some systems also provide a separate API call for large file opens (eg: fopen64() in MKS).
400Mb should not be considered a "large file" nowadays. I would reserve this for files larger than, say, 2Gb.
Also, just opening a file is very unlikely to give a segfault. WOuld you show us the code that access the file? I suspect some other factor is at play here.
UPDATE
I still can't tell exactly what's happening here. There are strange things that could be legitimate: you discard the first line and also the first token of each line.
You also assign to all the rownames[j] (except the first one) the address of dest which is a variable that has a block scope and whose associated memory is most likely to be reused outside that block. I hope you don't rely on rownames[j] to be any meaningful (but then why you have them?) and you never try to access them.
C99 allows you to mix variable declarations with actual instructions but I would suggest a little bit of cleaning to make the code clearer (also a better indentation would help).
From the symptoms I would look for some memory corruption somewhere. On small files (and hence less tokens) it may go unnoticed, but with larger files (and many more token) it fires a segfault.

Resources