I am unable to read the data from the file created. This is a very simple code and I simply cannot understand why it is not working. I have just shifted to mac and installed the developer command line tools.
My code is :
int main()
{
FILE *fp;
int lines = 0;
char *data;
data = (char *)malloc(1000);
data = NULL;
fp = fopen("1.txt", "r");
while (fgets(data, 1000, fp) != NULL)
{
printf("%s\n", data);
lines++;
}
printf("Lines = %d\n", lines);
free(data);
fclose(fp);
return 0;
}
You allocate space for data and then promptly leak it.
char *data;
data = (char *)malloc(1000);
data = NULL;
You then use fgets() with a NULL pointer, which causes undefined behavior.
fgets(data, 1000, fp)
Perhaps you should remove this line of code?
data = NULL;
Related
my code keeps throwing a segmentation fault from internal c libraries, my code is the following:
char *vertexShaderCode = (char *)calloc(1024, sizeof(char));
FILE *shaderFile;
shaderFile = fopen("./shaders/vertex.glsl", "r");
if(shaderFile)
{
//TODO: load file
for (char *line; !feof(shaderFile);)
{
fgets(line, 1024, shaderFile);
strcat(vertexShaderCode, line);
}
it is meant to load all the data from a file as a c string, line by line. can anyone help?
You want this:
char *vertexShaderCode = (char *)calloc(1024, sizeof(char));
FILE *shaderFile;
shaderFile = fopen("./shaders/vertex.glsl", "r");
if (shaderFile == NULL)
{
printf("Could not open file, bye.");
exit(1);
}
char line[1024];
while (fgets(line, sizeof(line), shaderFile) != NULL)
{
strcat(vertexShaderCode, line);
}
You still need to make your that there is no buffer overflow. Possibly you need touse realloc in order to expand the buffer if the initial length of the buffer is too small. I leave this as an exercise to you.
Your wrong code:
char *vertexShaderCode = (char *)calloc(1024, sizeof(char));
FILE *shaderFile;
shaderFile = fopen("./shaders/vertex.glsl", "r"); // no check if fopen fails
for (char *line; !feof(shaderFile);) // wrong usage of feof
{ // line is not initialized
// that's the main problem
fgets(line, 1024, shaderFile);
strcat(vertexShaderCode, line); // no check if buffer overflows
}
I have to do a function that reads a text file with characters. It is obligatory to use malloc and realloc. I made this code, whitout errors, but when I try to read file, I get runtime error. And I can't understand where is the problem in this code.
void openFile(FILE** file,char* filename)
{
int SIZE=10;
char* data,*data2;
int n = 0;
char c;
printf("filename:");
scanf("%s",&*filename);
if (!((*file) = fopen(filename, "r")))
perror("Error:");
else
{
if ((data = (char*)malloc(SIZE * sizeof(char))) == NULL)
{
perror("malloc:");
}
while (fscanf((*file),"%s",c) != EOF)
{
if (n < SIZE)
{
data[n++] = c;
}
else
{
if ((data2 = (char*)realloc(data, SIZE * sizeof(char))) != NULL)
{
data = data2;
data[n++] = c;
}
else
{
free(data);
}
}
}
}
}
There are some issues with your code, almost none of them fatal, deppending on what you pass to the function.
The catastrophic failure is probably because in your fscanf function you using "%s" specifier with a char variable, the correct specifier is %c, and you need to pass the address of the variable &c.
You should address scanf("%s", &*filename);, there is the danger of the data exceeding the storage capacity of the memory buffer, you should allways define a max size not larger than the capacity of the buffer, you can use "%99s" specifier with scanf for a memory buffer of 100 characters, or better yet, using fgets:
fgets(filename, sizeof(filename), stdin);
filename[strcspn(filename, "\n")] = '\0'; //to remove newline character
The way you are using the file pointer makes me suspect that you wouldn't need to pass it as an argument and much less as a double pointer, this would be useful if you need to keep the pointer to the file stream outside the function, if that's the case, you can leave it as is, otherwise you can use a local variable and close the stream when you are finished.
Here is he code with some corrections as mentioned, and some other minor ones:
void openFile(char *filename)
{
int SIZE = 10;
char *data, *data2;
int n = 0;
char c;
FILE *file; //local variable
printf("filename:");
scanf("%99s", filename);// &* is pointless, using %99s, assuming filename[100]
if (!(file = fopen(filename, "r")))
perror("Error:");
else
{
if ((data = malloc(SIZE)) == NULL) //char size is always 1 byte, no cast needed, include stdlib.h
{
perror("malloc:");
}
while (fscanf(file, "%c", &c) != EOF) //specifier for char is %c, furthermore you need & operator
{ //probably the source of your problems
if (n < SIZE)
{
data[n++] = c;
}
else
{
if ((data2 = realloc(data, SIZE)) != NULL) // again no cast, no sizeof(char)
{
data = data2;
data[n++] = c;
}
else
{
free(data);
}
}
}
fclose(file); //close file stream
}
}
Note that the only catastrophic problems are the ones with fscanf, you can fix those only and the code will likely work, I'd still advise the other fixes.
FILE *fp;
fp = fopen(filen, "wb");
const char tok[2] = ",";
char str[340];
while (fgets(str, 340, stdin) != NULL)
{
struct test loadTest;
printf("You entered: %s", str);
strncpy(loadTest.level, strtok(str, tok), 20);
strncpy(loadTest.first, strtok(NULL, tok), 30);
fwrite(&loadTest, sizeof(struct test), 1, fp);
}
fclose(fp);
Hello all,
For some reason I'm getting a segmentation fault error in my code.
I'm almost positive the error is somewhere within the small code block above (since that's all I modified for the seg fault), but I can't seem to pinpoint it.
I know segmentation faults have to do with accessing memory I shouldn't be accessing, but I'm not sure where I am even doing that in the code.
Any help would be greatly appreciated!
Some improvements of your code
check result of fopen before read/write to file
initialize variables before using their values
use sizeof instead of constant (as mentioned in comments)
strtok() can return NULL and this must be checked (see here why)
you must use strncpy() carefully because of this
Here is corrected version of your code
FILE *fp;
fp = fopen(filen, "wb");
if (fp == NULL)
{
printf("Error opening file: %s", filen);
}
else
{
const char tok[2] = ",";
char str[340];
while (fgets(str, sizeof(str), stdin) != NULL)
{
struct test loadTest;
char *level;
char *first;
memset(&loadTest, 0, sizeof(loadTest));
printf("You entered: %s", str);
level = strtok(str, tok);
if (level == NULL)
{
continue; // bad input ?
}
first = strtok(NULL, tok);
if (first == NULL)
{
continue;
}
strncpy(loadTest.level, level, sizeof(loadTest.level)-sizeof(char));
strncpy(loadTest.first, first, sizeof(loadTest.first)-sizeof(char));
fwrite(&loadTest, sizeof(loadTest), 1, fp);
}
fclose(fp);
}
Having an issue with my fwrite() and fread() dealing with a binary file here is my source code, and towards the bottem are my read and write. Right now it is returning 'jake' when I run it, and nothing else. I was told to write a dump buffer function to deal with the binary characters. In addition here is the text file as well, I am writing to a blank file called info.bin. PS I know that it is bad practice to save the zip as an int but this is what my professor is asking for.
File:
mike|203-376-5555|7 Melba Ave|Milford|CT|06461
jake|203-555-5555|8 Melba Ave|Hartford|CT|65484
snake|203-555-5555|9 Melba Ave|Stamford|CT|06465
liquid|203-777-5555|2 Melba Ave|Barftown|CT|32154
Code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define LINE 80
#define RECORDS 10
struct info{
char name[100];
char number[100];
char address[100];
char city[100];
char state[100];
int zip;
};
void dump_buffer(void *buffer, int buffer_size)
{
int x;
for(x = 0; x < buffer_size; x++)
{
printf("%c",((char *)buffer)[x]);
}
}
int i, j, seeker;
int main(int argc, char* argv[])
{
char *buffer;
struct info input_records[RECORDS];
int nrecs = 0;
unsigned long fileLen;
char line[LINE];
FILE *fp = NULL;
FILE *fpbin = NULL;
FILE *fpread = NULL;
if (argc != 2)
{
printf ("ERROR: you must specify file name!\n");
return 1;
}
/* Open file */
fp = fopen(argv[1], "r");
if (!fp)
{
perror ("File open error!\n");
return 1;
}
while (!feof (fp)) {
fgets(line, sizeof(line),fp);
char* tok = strtok(line, "|");
while(tok != NULL)
{
strcpy(input_records[nrecs].name, tok);
tok = strtok(NULL, "|");
strcpy(input_records[nrecs].number, tok);
tok = strtok(NULL, "|");
strcpy(input_records[nrecs].address, tok);
tok = strtok(NULL, "|");
strcpy(input_records[nrecs].city, tok);
tok = strtok(NULL, "|");
strcpy(input_records[nrecs].state, tok);
tok = strtok(NULL, "|");
input_records[nrecs].zip = atoi(tok);
tok = strtok(NULL, "|");
}
nrecs++;
}
fpbin = fopen("info2.bin", "wb");
if (!fp)
{
perror ("File open error!\n");
return 1;
}
for(i = 0; i < 4; i++)
{
fwrite(&input_records[i], sizeof(struct info), 200000, fpbin);
}
fclose(fpbin);
fpread = fopen("info2.bin", "rb");
fseek(fpread, 0, SEEK_END);
fileLen = ftell(fpread);
fseek(fpread, 0, SEEK_SET);
buffer = (char *)malloc(sizeof(struct info));
fread(buffer, fileLen, 1, fpread);
dump_buffer(buffer, sizeof(buffer));
fclose(fpread);
fclose(fp);
free(buffer);
return 0;
}
fwrite(&input_records[i], sizeof(struct info), 200000, fpbin);
You just told fwrite to write 200000 * sizeof(struct info) bytes to the file, starting at the address of input_records[i]. That accesses memory far beyond what has been allocated for input_records, the behaviour is undefined, but a segmentation fault is not unlikely. I'm actually surprised that apparently it didn't crash for you.
buffer = (char *)malloc(sizeof(struct info));
fread(buffer, fileLen, 1, fpread);
You're trying to read fileLen bytes into a buffer of size sizeof(struct info). If fileLen > sizeof(struct info), that is again undefined behaviour, and if fileLen is sufficiently larger, likely to crash.
You should let fwrite one object of size sizeof(struct info) each time, and you should allocate fileLen bytes for the buffer you read in (or read in chunks of size sizeof(struct info)). And you should check the return values of fwrite and fread to know whether they succeeded in writing/reading the desired data and handle failures appropriately.
fpbin = fopen("info2.bin", "wb");
if (!fp)
{
You check the wrong FILE* here, and you don't check fpread at all.
Further, you pass the wrong count to dump_buffer,
dump_buffer(buffer, sizeof(buffer));
buffer is a char*, so sizeof buffer is the size of a char*, typically four or eight bytes. You should pass the allocated size of the buffer there.
And, when reading the original file,
while (!feof (fp)) {
fgets(line, sizeof(line),fp);
feof(fp) only becomes true after an attempt to read was made when the end of the file has been reached, you should change your loop condition to
while(fgets(line, sizeof line, fp) != NULL) {
Finally, your tokenizing code will fail badly if the input file contains malformed data, or too long lines. You should also add checks there, so that you don't pass a NULL to strcpy or atoi.
I have the following function:
void read_file(char* path, char** data)
{
FILE* file = NULL;
size_t size, result = 0;
*data = NULL;
file = fopen(path, "rb");
if (file == NULL)// error opening file
{
return;
}
fseek(file, 0, SEEK_END);
size = ftell(file) + 1;
rewind(file);
*data = (char*)malloc(size);
if(*data == NULL)
return;
result = fread(*data, 1, size, file);
if (result != size - 1)// error reding file
{
*data = NULL;
}
printf("LINE=%u\n", __LINE__);
(*data)[size-1] = '\0';
printf("LINE=%u\n", __LINE__);
fclose(file);
return;
}
I am getting a Segmentation fault on the line right in between the two printf("LINE=%u\n", __LINE__); statements. I don't understand why this is. When I'm looking at this line, it seems (*data) would have a type of (char *) which should certainly be able to be used with the index operator [].
What am I missing?
Probably the if (result != size - 1) test is failing and then you reset *data to NULL (which is a memory leak, BTW), and then you try to write to (*data)[size-1] - oops !
some pointers:
ftell returns -1 on failure, so if that is the case this will be 0 size = ftell(file) + 1;
size_t on some platforms is unsigned int, it may be good to have that in mind.
doing *data = NULL; is not a good idea, free it first free( *data );
put some if statements in your code to catch errors, don't assume everything will work
e.g. assert( size>0 );
I have tested your code and it works for me - I have added returning of file's size to properly pass the data to fwrite.
> ./a.out arm-2010.09-good.tar.bz2 | sha1sum && sha1sum arm-2010.09-good.tar.bz2
alloc size of 37265592
6bdff517bcdd1d279fc84ab3a5fbbca34211a87c -
6bdff517bcdd1d279fc84ab3a5fbbca34211a87c arm-2010.09-good.tar.bz2
furthermore Valgrind reports no warning and errors so .. loooks OK!
#include <stdio.h>
#include <stdlib.h>
size_t read_file(char* path, char** data)
{
FILE* file = NULL;
size_t size, result = 0;
*data = NULL;
file = fopen(path, "rb");
if (file == NULL)// error opening file
{
return 0;
}
fseek(file, 0, SEEK_END);
size = ftell(file) + 1;
rewind(file);
fprintf(stderr, "alloc size of %i\n", size);
*data = (char*)malloc(size);
if(*data == NULL)
return 0;
result = fread(*data, 1, size, file);
if (result != size - 1)// error reding file
*data = NULL;
(*data)[size-1] = '\0';
size--; // report file size
fclose(file);
return size;
}
int main(int argc, char** argv)
{
char* data;
if(argc<2)
return 0;
size_t siz = read_file(argv[1], &data);
if(data) {
fwrite(data, 1, siz, stdout);
free(data);
}
else {
fprintf(stderr, "No data returned\n");
}
return 0;
}
Here's the probable source of the problem:
if (result != size - 1)// error reding file
{
*data = NULL;
}
printf("LINE=%u\n", __LINE__);
(*data)[size-1] = '\0';
What happens if there is an error reading the file? You set *data to NULL, and then immediately try to dereference it - bad juju.
Note that this also results in a memory leak; you don't free the memory that *data points to.
Restructure your code so that (*data)[size-1] = '\0' is executed only if the read operation was successful:
if (result != size - 1)
{
free(*data);
*data = NULL;
}
else
{
(*data)[size-1] = 0;
}