SEGFAULT problem

D

difeiz

Greetings all,

I am working on a program and encountered a problem recently. The program is simplified (but the problem is still reproduceable):

Code:
#define _GNU_SOURCE
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

void
read_in_rates(const char *filename, double **rates)
{
int i, lines = 0;
char ch;

FILE *rates_file = fopen(filename, "r");
do {
ch = fgetc(rates_file);
if (ch == '\n') lines++;
} while (ch != EOF );

*rates = realloc(*rates, lines * sizeof(**rates));

rewind(rates_file);
for(i = 0; i < lines; i++) {
fscanf(rates_file, "%lf", &(*rates)[i]);
printf("%lf\n", *rates[i]);
}
}

int
main(void)
{
int i;
double *rates_1 = malloc(sizeof(*rates_1));

read_in_rates("./test", &rates_1);
for(i = 0; i <= 80; i++)
printf("%i\t%lf\n", i, rates_1[i]);

exit(EXIT_SUCCESS);
}

test file can be generated by:
~$ seq 1 100 > test

In main function I malloced a double pointer (rates_1) with a size of a double type, then I passed a pointer (&rates_1) to this double pointer (rates_1) to the function read_in_rates.

The read_in_rates function counted the lines in test file and trying to reallocate the pointer, access to the pointer (*rates) will guarantee a segfault when i >=1 on my machine.

I'm running this program on linux on virtualbox, memory spaces are plenty, I have several other malloc and realloc for some structure types and they are working fine, could anyone point out where the problem is? Thanks in advance.

Cheers,
Difei
 
B

Barry Schwarz

Greetings all,

I am working on a program and encountered a problem recently. The program is simplified (but the problem is still reproduceable):

Code:
#define _GNU_SOURCE
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

void
read_in_rates(const char *filename, double **rates)
{
int i, lines = 0;
char ch;

FILE *rates_file = fopen(filename, "r");[/QUOTE]

Did fopen succeed?
[QUOTE]
do {
	ch = fgetc(rates_file);[/QUOTE]

Is char signed or unsigned on your system?  fgetc returns an int.  You
should honor that interface.
[QUOTE]
if (ch == '\n') lines++;
} while (ch != EOF );

*rates = realloc(*rates, lines * sizeof(**rates));[/QUOTE]

Did realloc succeed?
[QUOTE]
rewind(rates_file);
for(i = 0; i < lines; i++) {
	fscanf(rates_file, "%lf", &(*rates)[i]);
	printf("%lf\n", *rates[i]);[/QUOTE]

What you have coded will be parsed as *(rates[i]).  When i is not 0,
rates[i] doesn't exist.  I think you want (*rates)[i].
[QUOTE]
}
}

int
main(void)
{
int i;
double *rates_1 = malloc(sizeof(*rates_1));[/QUOTE]

Did malloc succeed?
[QUOTE]
read_in_rates("./test", &rates_1);
for(i = 0; i <= 80; i++)
	printf("%i\t%lf\n", i, rates_1[i]);[/QUOTE]

How do you know that read_in_rates processed at least 80 lines.  It
would be better for the function to return an int telling you how many
lines.
[QUOTE]
exit(EXIT_SUCCESS);
}

test file can be generated by:
~$ seq 1 100 > test

In main function I malloced a double pointer (rates_1) with a size of a double type, then I passed a pointer (&rates_1) to this double pointer (rates_1) to the function read_in_rates.

Better terminology is pointer to double. Many take the phrase "double
pointer" to mean type** for some type.

You passed the address of rates_1. This is a pointer value and not a
pointer object.
The read_in_rates function counted the lines in test file and trying to reallocate the pointer, access to the pointer (*rates) will guarantee a segfault when i >=1 on my machine.


As noted above, the object you are dereferencing does not exist.
I'm running this program on linux on virtualbox, memory spaces are plenty, I have several other malloc and realloc for some structure types and they are working fine, could anyone point out where the problem is? Thanks in advance.

You need to look at operator precedence. See comment above.
 
I

Ike Naar

Code:
#define _GNU_SOURCE
#include <unistd.h>[/QUOTE]

The two lines above are unnecessary for this program.
[QUOTE]
#include <stdlib.h>
#include <stdio.h>

void
read_in_rates(const char *filename, double **rates)
{
int i, lines = 0;
char ch;[/QUOTE]

ch is used to store the result of fgetc, which is an int
because fgetc can return EOF which might be outside the
range of a char. So use 'int ch;',
[QUOTE]
FILE *rates_file = fopen(filename, "r");[/QUOTE]

You should check if fopen succeeds (i.e. returns
a non-null pointer-to-FILE).
[QUOTE]
do {
	ch = fgetc(rates_file);
	if (ch == '\n') lines++;
} while (ch != EOF );

*rates = realloc(*rates, lines * sizeof(**rates));[/QUOTE]

You should check if realloc succeeds (i.e. returns a
non-null pointer).
[QUOTE]
rewind(rates_file);
for(i = 0; i < lines; i++) {
	fscanf(rates_file, "%lf", &(*rates)[i]);
	printf("%lf\n", *rates[i]);[/QUOTE]

*rates[i] parses as *(rates[i]), but what is intended
here is certainly (*rates)[i].
[QUOTE]
}[/QUOTE]

Forgot to fclose(rates_file);
[QUOTE]
}

int
main(void)
{
int i;
double *rates_1 = malloc(sizeof(*rates_1));[/QUOTE]

You should check if malloc succeeds (i.e. returns a
non-null pointer).
[QUOTE]
read_in_rates("./test", &rates_1);
for(i = 0; i <= 80; i++)
	printf("%i\t%lf\n", i, rates_1[i]);[/QUOTE]

If the input file has less that 81 lines, the call
to read_in_rates will have resized rates_1 to less
than 81 elements, and you are accessing out-of-bounds
elements of rates_i in the printing loop.
[QUOTE]
exit(EXIT_SUCCESS);
}

test file can be generated by:
~$ seq 1 100 > test

This is very strange, test is used both for input and for output.
If the file is opened for output before it is opened for input
(which is most probably the case here) then the contents of the
file are lost before they are used.
 
D

difeiz

Hi Barry,

The program is simplified for reading so rellocs and mallocs checking are removed, the "80" thing is just a placeholder, as you pointed out, the operator precedence caused the SEGFAULT problem, thank you very much for your help.

Greetings all,
I am working on a program and encountered a problem recently. The program is simplified (but the problem is still reproduceable):
Code:
[/QUOTE]

#define _GNU_SOURCE[/QUOTE]
[QUOTE]
#include <unistd.h>[/QUOTE]
[QUOTE]
#include <stdlib.h>[/QUOTE]
[QUOTE]
#include <stdio.h> 


read_in_rates(const char *filename, double **rates) 

int i, lines = 0;[/QUOTE]
[QUOTE]
char ch; 

FILE *rates_file = fopen(filename, "r");[/QUOTE]



Did fopen succeed?


[QUOTE]
do {[/QUOTE]
[QUOTE]
ch = fgetc(rates_file);[/QUOTE]



Is char signed or unsigned on your system?  fgetc returns an int.  You

should honor that interface.


[QUOTE]
if (ch == '\n') lines++;[/QUOTE]
[QUOTE]
} while (ch != EOF ); 

*rates = realloc(*rates, lines * sizeof(**rates));[/QUOTE]



Did realloc succeed?


[QUOTE]
rewind(rates_file);[/QUOTE]
[QUOTE]
for(i = 0; i < lines; i++) {[/QUOTE]
[QUOTE]
fscanf(rates_file, "%lf", &(*rates)[i]);[/QUOTE]
[QUOTE]
printf("%lf\n", *rates[i]);[/QUOTE]



What you have coded will be parsed as *(rates[i]).  When i is not 0,

rates[i] doesn't exist.  I think you want (*rates)[i].


[QUOTE]
} 





int i;[/QUOTE]
[QUOTE]
double *rates_1 = malloc(sizeof(*rates_1));[/QUOTE]



Did malloc succeed?


[QUOTE]
read_in_rates("./test", &rates_1);[/QUOTE]
[QUOTE]
for(i = 0; i <= 80; i++)[/QUOTE]
[QUOTE]
printf("%i\t%lf\n", i, rates_1[i]);[/QUOTE]



How do you know that read_in_rates processed at least 80 lines.  It

would be better for the function to return an int telling you how many

lines.


[QUOTE]
[QUOTE]
exit(EXIT_SUCCESS);[/QUOTE]
[QUOTE]
}[/QUOTE]
[QUOTE]

test file can be generated by:
~$ seq 1 100 > test

In main function I malloced a double pointer (rates_1) with a size of a double type, then I passed a pointer (&rates_1) to this double pointer (rates_1) to the function read_in_rates.



Better terminology is pointer to double. Many take the phrase "double

pointer" to mean type** for some type.



You passed the address of rates_1. This is a pointer value and not a

pointer object.


The read_in_rates function counted the lines in test file and trying to reallocate the pointer, access to the pointer (*rates) will guarantee a segfault when i >=1 on my machine.




As noted above, the object you are dereferencing does not exist.


I'm running this program on linux on virtualbox, memory spaces are plenty, I have several other malloc and realloc for some structure types and they are working fine, could anyone point out where the problem is? Thanks in advance.



You need to look at operator precedence. See comment above.
 
I

Ike Naar

This is very strange, test is used both for input and for output.
If the file is opened for output before it is opened for input
(which is most probably the case here) then the contents of the
file are lost before they are used.

Sorry, forget this one, I was confused about the 'seq 1 100 > test'
command and thought it was a run of the program you showed.
It appears, however, that 'seq' is a Unix utility.
 
I

Ian Collins

Greetings all,

I am working on a program and encountered a problem recently. The program is simplified (but the problem is still reproduceable):

Code:
#define _GNU_SOURCE 
Why?

#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>

void
read_in_rates(const char *filename, double **rates)
{
int i, lines = 0;
char ch;

FILE *rates_file = fopen(filename, "r");
do {
	ch = fgetc(rates_file);
	if (ch == '\n') lines++;
} while (ch != EOF );

*rates = realloc(*rates, lines * sizeof(**rates));

rewind(rates_file);
for(i = 0; i<  lines; i++) {
	fscanf(rates_file, "%lf",&(*rates)[i]);
	printf("%lf\n", *rates[i]);[/QUOTE]

This is probably your problem, you are indexing then dereferencing
rather than dereferencing then indexing.  See the line above for the
correct form.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top