Bus error. Cannot access memory - c

I'm getting bus error.
While debugging the snippet below and stepping to the end of writeDmpFile I'm getting:
writeDmpFile (tree=0x56a310, filename=0x7fffffffd450 "20140318.221058") at unzipper_m1.c:146
146 }
(gdb) n
Cannot access memory at address 0x38353031323236
The file is written though, but program ends with bus error.
Here the code:
typedef struct dmpParams_t
{
char buff[6000000];
size_t *size;
}dmpParams_t;
int writeFile(char *name, unsigned char *buff, size_t *size,const char *dir )
{
FILE * pFile;
chdir (dir);
pFile = fopen ( name, "wb");
fwrite (buff , sizeof(unsigned char), *size, pFile);
fclose (pFile);
return 1;
}
int writeDmpFile(GTree *tree, char *filename)
{
char dmpfilename[32];
dmpfilename[0] ='\0';
dmpParams_t params;
params.buff[0] ='\0';
size_t size =0;
params.size=&size ;
g_tree_foreach(tree, (GTraverseFunc)writeDmpFileLine, &params);
sprintf (dmpfilename, "InstrumentList_FULL.csv_%.*s", 15, filename);
writeFile(dmpfilename, ( unsigned char *)params.buff, &size , dmpdir);//(size_t *)params.size, dmpdir);
}

It looks like a buffer overrun of dmpfilename. You allocated an array of length 32. You then format it with "InstrumentList_FULL.csv_%.*s". That's 24 characters, plus 15 for the filename, plus a null terminator. That's more than 32.
Increase the size of the buffer.
Oh, and dmpParams_t is, er, rather large. Perhaps there's a stack overflow when you allocate one of those as a local.
Some other comments:
You could usefully use const a bit more.
Declaring size as size_t* in the struct is a bit odd. You pass the address of the struct to g_tree_foreach. I'd declare size as size_t and let g_tree_foreach modify the value.
Likewise, it seems odd that you pass the address of size to writeFile. Again a const value seems to make more sense.

Related

reading a big bin-file(~2mb) in c

I want to read a bin-file with a size under 2mb.
At the moment my code for reading the bin file looks like this:
edit:
#define MAX_BYTES_IN_FILE 500000 // ~ 2mb
#define ERROR_FILE 1
int get_byte_from_file(FILE *stream, unsigned char *dataarray) {
int counter = 0;
while ((dataarray[counter] = fgetc(stream)) != EOF) {
counter += 1;
}
return counter;
}
Main looks like this for the example use of the function.
int main(int argc, char **argv) {
FILE *datei;
unsigned int number_of_bytes;
unsigned char *dataarray;
dataarray = (unsigned char *)malloc(sizeof(unsigned char) * MAX_BYTES_IN_FILE);
datei = fopen(argv[1], "rb");
number_of_bytes = get_byte_from_file(datei, dataarray);
for (int i = 0; i < number_of_bytes; i++)
printf("%x ", dataarray[i]);
return 0;
}
Maybe I did a simple mistake but cant see it the error is still: Segmentation fault (core dumped)
This line is sufficient to crash your program:
while ((dataarray[counter] = fgetc(stream)) != EOF) {
Let's go through it step by step:
fgetc(stream) reads a byte and returns its value or EOF. Because a byte can have any possible value, fgetc() returns a larger int, which can hold an EOF value that is distinct from any byte value that might be found in the file.
You assign this int value to an unsigned char. An EOF value will be truncated to this datatype.
The value of the assignment is of type unsigned char, and the converted EOF value is not equal to EOF anymore. Thus, the comparison always fails, and your program keeps fetching data until the buffer overruns and nasty things begin to happen.
You need to store the result of fgetc() in an int variable until you've checked that it is indeed not the EOF value.
Maybe something like this.
void *readfile(FILE *fi, long *filesize)
{
void *buff;
fseek(fi, 0, SEEK_END);
*filesize = ftell(fi);
fseek(fi, 0, SEEK_SET);
buff = malloc(*filesize);
if(buff)
{
fread(buff, 1, *filesize, fi);
}
return buff;
}
You need to add error checks- I did not as it is only the idea.
And your usage:
int main(int argc, char **argv) {
FILE *datei;
long number_of_bytes;
unsigned char *dataarray;
datei=fopen(argv[1],"rb");
dataarray = readfile(datei, &number_of_bytes);
for (int i=0;dataarray && i<number_of_bytes;i++)
printf("%hhx ",dataarray[i]);
return 0;
}
The reason you get a segmentation fault is your allocation is incorrect: you allocate MAX_BYTES_IN_FILE bytes instead of unsigned int elements. As allocated, the array has only MAX_BYTES_IN_FILE / sizeof(unsigned int) elements, whereas the file is probably MAX_BYTES_IN_FILE * sizeof(unsigned int) bytes long.
You are reading bytes from the file (values between 0 and 255) but you use unsigned int elements. What is the logic? Does the file contain 32-bit values or individual bytes?
Once you can confirm that the file contents is exactly the same as the representation of the array in memory, you can use fread() to read the whole file in a single call.

How to read from pipe into a file?

I would like to read from the pipe straight into a file with the code below. base_fd is a pipe.
FILE* fp = fopen("dec_data", "wb+");
int r_result;
int len = msg_length-part-3; //set to 75933
while ((r_result = read(base_fd[0], fp, len))) {
printf("r_result: %d \n", r_result);
len -= r_result;
}
The read seems to happen fine, with r_result showing 65536 and then 10397 as required. However, when I inspect the file I created, it has a size of 0 bytes...
You have a semantic error in your code.
Take a look at the read(2) system call signature:
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
The second parameter to the function is a void pointer (void *buf), which is where read will store the count bytes it reads from fd descriptor.
However, a FILE * is an abstraction of the C library. In this answer you can see more of it. The struct FILE in MinGW32 5.1.4 is:
typedef struct _iobuf
{
char* _ptr;
int _cnt;
char* _base;
int _flag;
int _file;
int _charbuf;
int _bufsiz;
char* _tmpfname;
} FILE;
What read will do is similar to how we copy strings. Consider this function:
void strcpy(char *dst, char *src)
{
while(*src) *dst++ = *src++;
}
This function will copy the contents from src into dst until it finds a NULL terminating byte. This is obviously a very flawed function and should never be used, but illustrates why your example doesn't work.
Under the hood, what read is doing is very similar to this strcpy function: it is overwriting a lot of bytes in memory starting at the address pointed to by the fp pointer. You are effectively losing your reference to the FILE * pointer and the resources associated to it.
I'll bet that if you try to close(fp) after that loop you'll get a segmentation fault (it's Undefined Behavior, but I'll bet anyway).
The right way to do what you want is:
FILE* fp = fopen("dec_data", "wb+");
char *buf;
int r_result;
int len = msg_length - part - 3; //set to 75933
buf = malloc(len);
if(!buf) {
perror("malloc");
exit(EXIT_FAILURE);
}
while ((r_result = read(base_fd[0], buf, len))) {
fprintf(fp, buf);
len -= r_result;
}
free(buf);
close(fp); // now it closes the file pointer

segment fault after parsing unsigned char to int pointer

I'm facing a problem when trying to read a binary file of fixed size. The code below returns segmentation Fault just before closing the file. What I want to achieve it is to return an int pointer back to the main function.
The file it s a raw grayscale image, which has values from 0 to 255, that's why I'm using unsigned char.
How can I convert and assign from unsigned char to *int properly?
Any kind of help will be welcome!
void readBinaryFile(char *filename, int *in){
FILE *file;
long length;
unsigned char *imagen;
int c;
file = fopen(filename, "rb");
fseek(file,0,SEEK_END);
length = ftell(file);
imagen = (unsigned char *) malloc(length);
fseek(file, 0, SEEK_SET);
fread(imagen, length, 1 , file);
int cont;
//c+4: file contains values from 0 to 255
for(c=0,cont=0;c<length;c=c+4,cont++){
in[cont] = (unsigned char) imagen[c];
}
for(cont=0;cont<length/4;cont++){
printf("%d",(int) in[cont]);
}
fclose(archivo);
free(imagen_buffer);
}
void main(int argc, char **argv){
int *in;
int fixed_size = 784;
in = (int *) malloc((fixed_size)*(fixed_size));
readBinaryFile("test.raw", in);
int c;
for(c=0;c<((fixed_size)*(fixed_size));c++){
printf("%d", (unsigned char) in[c]);
}
}
This
int *in;
makes in point to an int.
This
in = (int *) malloc((fixed_size)*(fixed_size));
allocates to in 784*784=614656 bytes.
You need 784*784 ints.
An int needs sizeof (int) bytes, which by definition is very well might be and most often is larger then 1.
From 1. and 2. above it can be deduces that 784*784 int needs more then 784*784 bytes.
So change
in = (int *) malloc((fixed_size)*(fixed_size));
to be
in = (int *) malloc((fixed_size)*(fixed_size) * sizeof (int));
or even nicer and safer with less noise do
in = malloc(fixed_size*fixed_size * sizeof *in);
because
in C there is no need to cast void* (which malloc() returns).
the parentheses around fixed_size are useless.
using sizeof *in returns the same as sizeof (int), but would "survive" if you changed int * in to become for example unsigned * in.
Also while reading you need to make sure to not read more then 784*784 char, as else the memory allocated for the int will be overflowed, which in turn invoked the infamous Undefined Behaviour.

C Pointer of array of strings garbled when retreived later

I have read a lot of the answers on the theoretical issues with memory allocation to pointer to arrays, but have not been able to fix my code...so turning to you.
I have an array of strings in a STRUCT, which I need to write to and read from. Declared as:
typedef struct client_mod
{
/* Client ad_file */
char *ad_filenames[10];
/* Client's current ad array index*/
unsigned int ad_index;
} client;
Then , inside a function , I assign values to pointer:
static int get_spots (client_mod *client)
{
char buf[512];
FILE *ptr;
if ((ptr = popen("php /media/cdn/getspot.php", "r")) != NULL) {
/* Read one byte at a time, up to BUFSIZ - 1 bytes, the last byte will be used for null termination. */
size_t byte_count = fread(buf, 1, 512 - 1, ptr);
/* Apply null termination so that the read bytes can be treated as a string. */
buf[byte_count] = 0;
}
(void) pclose(ptr);
// parse extracted string here...
int i = 0;
client->ad_filenames[i] = strdup(strtok(buf,"|"));
while(client->ad_filenames[i]!= NULL && i<5)
{
client->ad_filenames[++i] = strdup(strtok(NULL,"|"));
if (client->ad_filenames[i] != NULL && strlen(client->ad_filenames[i]) > 5) {
LOG("TESTING FOR CORRECT FILE NAMES %s\n", client->ad_filenames[i]);
}
}
}
The problem comes when I retreive the values later:
/* in looping code block */
LOG("Checking file under index = %d, file is %s", client->ad_index, client->ad_filenames[client->ad_index]);
The first two members of the array are retreived normally, everything after that is garbled.
I would appreciate any guidance. Thanks!
I understand this probablby comes from undefined behaviour of assigning directly to the pointer, but I can't figure out how to solve it.
I think the problem is with assigning to this struct element.
char *ad_filenames[10];
ad_filenames is an array of 10 of pointer to characters.
What that means is that memory allocation is needed for each index.
Something like
client->ad_filenames[0] = strdup(var1);
strdup() does both malloc() and strcpy() within this function.
client should be a variable name. You already defined client as a type.
Here is working code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct client_mod
{
/* Client ad_file */
char *ad_filenames[10];
/* Client's current ad array index*/
unsigned int ad_index;
}CLIENT1;
CLIENT1 *client;
int func( char *var1 ) {
client->ad_filenames[0] = strdup(var1);
}
int
main(void)
{
char str1[10];
client = malloc( sizeof client );
strcpy( str1, "Hello" );
func( str1 );
printf("%s\n", client->ad_filenames[0] );
free(client->ad_filenames[0]);
free (client);
}
Your problem is with the line,
size_t byte_count = fread(buf, 1, 1000 - 1, ptr);
Read the man fread page,
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
you read 1000-1 members of size 1 into buf, which is only allocated buf[512], either expand buf or decrease fread 3rd argument,
buf[1000+1];
size_t byte_count = fread(buf, 1, sizeof(buf)-1, ptr);

How to copy char array to a double pointer in C

Im writing a fairly simple program to read a file line by line and store it into an array of lines, my program compiles fine but it crashes everytime I run it.
This is my code:
#include <stdio.h>
#include <string.h>
#define LINESIZE 512
typedef struct {
char **data;
size_t nused;
} lines_t;
lines_t readlines(FILE *fp);
int main(int argc,char* argv[]) {
FILE *fp;
(void)argc;
if((fp = fopen(argv[1],"r+")) == 0) {
perror("fopen");
}
readlines(fp);
return 0;
}
lines_t readlines(FILE *fp) {
lines_t line_data;
char line[LINESIZE];
char temp[20];
int num_lines = 0;
(*line_data.data) = (char *)malloc(LINESIZE);
while(fgets(line,LINESIZE,fp)) {
sscanf(line,"%s\n",temp);
strcpy(line_data.data[num_lines], temp); /* Program crashes here */
num_lines++;
}
return line_data;
}
The line where I try to copy my array is giving me trouble, So my question is, How do I copy my character array temp into the char **data inside struct lines_t if I am not doing it right?
You are dereferencing an invalid pointer here:
(*line_data.data) = (char *)malloc(15);
line_data.data is a char **. You are trying to deference it but it is not yet set to any meaningful value. You need to allocate memory for line_data.data before you allocate memory for *line_data.data.
(char *)malloc(15) is particularly suspicious also. Where does 15 come from and what are you actually allocating memory for? Casting the result of malloc is generally considered bad practice, and in your case, rightly so, because malloc is declared in stdlib.h and you aren't including that header. If you want to allocate enough space to hold 15 char *, then use malloc(15 * sizeof(char *)) or alternatively, malloc(15 * sizeof(*line_data.data)) (here it is safe to use *line_data.data even if it doesn't point to anything, because sizeof does not evaluate its operand).
You can try malloc line_data.data before strcpy.
lines_t readlines(FILE *fp) {
lines_t line_data;
line_data.data = malloc(LINESIZE);
*line_data.data = malloc(LINESIZE);
return line_data;
}
You first need to allocate memory.
You need to allocate both for the array of strings and string array. Here you need to have an upper limit while calling a malloc.
line_data = malloc(10* sizeof(char*)); // for example here the upper limit is 10
while(fgets(line,LINESIZE,fp)) {
sscanf(line,"%s\n",temp);
line_data.data[num_lines] = malloc(sizeof(char) * (strlen(temp)+1));
strcpy(line_data.data[num_lines], temp); /* Program crashes here */
num_lines++;
}

Resources