I was trying to open a binary file in the directory and perform the operations accordingly.I doubt this line..is not the correct way of representation to work the below logic.
int main(int argc, char* argv[])
{
int k=0;
FILE *fp;
unsigned char cd[255];
unsigned long cd1[500];
char *buffer;
unsigned long sa=80044;
int j=0,i=0,n=0;
DIR *dir;
struct dirent *direntry; //could be a file, or a directory
dir = opendir("C:/Documents and Settings/Administrator/Desktop/vicky");
if(!dir) {
printf("Error: directory did not open!\n");
return 1;
}
while((direntry=readdir(dir))!=NULL) {
if(++k < 100)
{
printf("%s\n",direntry->d_name);
sprintf(buffer,"%s",direntry->d_name);//here i got the unhanded exception.
fp=fopen("buffer","rb");
sa=sa-44;
sa=sa/8;
if(fp==NULL)
{
printf("file not found!");
}
else
{
for(j=0;j<(sa);j++)
{
for(i=0;i<8;i++)
{
cd[i]=fgetc(fp);//get each character from file
// printf("%c",cd[i]);
}
if(i==8)//if the i is 8 the character then do the following,just read 8 bytes and then calculate the cd1.
{
sa=sa-8;
cd1[j]=(cd[6] * 65536 + cd[5] * 256 + cd[4]);//multiply the positional weightage and calculate the cd1,which contains the 7 digits decimal value.
//if((cd1[j]> 0x7FFFFF)&&(cd1[j]<=0xFFFFFF))
//cd1[j]=cd1[j]- 0xFFFFFF;
//cd1[j]=cd1[i] * -1;
}
printf("completes first 8 bytes read:%d - %d",j,cd1[j]);//print j and cd1[j] value in console window
}
fclose(fp);//close the file
}
}
if((strcmp(direntry->d_name, "text.txt"))==0) {
printf("\nThe %s file has been found\n",direntry->d_name);
k=-99; //just a flag value to show the file was found
break;
}
}
if(k!=-99)
printf("\nThe test.txt file was not found\n");
closedir(dir);
printf("\n");
getchar();
return 0;
}
This is error i got:Unhandled exception at 0x1029a189 (msvcr90d.dll) in READ_TEXT.exe: 0xC0000005: Access violation writing location 0xcccccccc.Kindly let me any suggestion to read the "direntry->d_name" file name to process the above logic.
Make the character buffer an ordinary array, for simplicity's sake:
char buffer[1024];
That way you're sure to have the memory put aside and ready to use. You should use snprintf() if your platform provides it.
buffer is not allocated. sprintf() is basically attempting to write "nowhere".
The destination variable needs to be either allocated on the heap using malloc or on the stack restricting its use to the current scope.
You have only declared char* buffer, not allocate memory for it using malloc().
Your problem is an uninitialized pointer.
Initialize the pointer with malloc or try an array
char buffer[1024];
change
char * buffer;
to
char buffer[MAX_PATH];
or something similar.
U must allocate the memory for the buffer variable.
char *buffer; statement is not allocating any memory so that i could have
any data.
so better u try
chat buffer[//buffer length];
or char *buffer = new char(//buffer length);
or char buffer = (char)malloc(//buffer length);
these above statement will allocate memory and fix your issue.
Related
I'm trying to read file using file descriptor. The file descriptor is correct, so, the file is open correctly. The error is given when the program reads the last line
This is the code:
void readFile(char* filePath){
int fd,i=0;
char *c= NULL;
int read=1;
fd = open(filePath, O_RDONLY );
char **config;
config=(char**)malloc(4 * sizeof(char*));
if(fd<0){
printf("Error");
} else {
while (read==1){
c=readLine(fd);
if(*c=='\0'){
read=0;
}else{
config[i]=(char*) malloc(sizeof(char));
strcpy(config[i], c);
i++;
}
}
close(fd);
}
}
char *readLine(int fd){
char character;
char *array= malloc(1);
unsigned int siz=1;
while (read(fd, &character, 1) > 0 && character!='\n'){
array=realloc(array, siz + 1);
array[siz - 1]=character;
siz ++;
}
array[siz - 1]='\0';
return array;
The program has several flaws, including not freeing dynamically allocated memory (that returned by readline for example).
However, what is preventing the program to run at least is the lack of space of each of the config[i] locations. You just reserve space for one character malloc(sizeof(char)), but you have to reserve space for the whole string that afterwards is copied, plus the ending '\0': malloc(strlen(c) + 1). Also, take into account that using strlen, strcpy, etc. expects the string to contain non-binary data, and may fail with different encodings, etc.
Another solution would be to just assign config[i] to the returned c string, and later freeing it when freeing config. You would avoid the copy of the string.
i'm trying to read a file and split this file into multiple buffers.
This is what i came up with:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define PKT_SIZE 2048;
#define PATH "directory of some kind"
int main() {
char filepath[200] = PATH;
FILE *packet;
int size = PKT_SIZE;
char *buffer[size];
int i=0;
//OPEN FILE
if((packet = fopen(filepath, "r")) == NULL){ //I'm trying with a txt file, then i'll change it to 'rb'
printf("Error Opening File\n");
return -1;
}
//READ FILE
while(*fgets((char *) *buffer[i], (int) strlen(buffer[i]), packet) != NULL) { //read the file and cycling insert the fgets into the buffer i
printf("Create %d buffer\n", i);
i++;
}
fclose(packet);
return 0;
}
Now, when i run this program, i get a SIGSEGV error, i managed to understand that this error is definetly:
*fgets((char *) *buffer[i], (int) strlen(buffer[i]), packet) != NULL
Do you have any suggestions?
*fgets((char *) *buffer[i], (int) strlen(buffer[i]), packet)
This line as several problems.
buffer[i] is just an un-initialized pointer pointing nowhere.
*buffer[i] is of type char you need to pass the char*.
strlen is not returning the size of the buffer. It is undefined behavior here because you called it over uninitialized pointer value.
Also dererencing whatever fgets is return is bad when the fgets returns NULL. It invokes undefined behavior.
There many solutions to this ranging from dynamic memory allocation to using
char buffer[size][MAXSIZE];. If you go about this you can get input this way:
#define MAXSIZE 100
...
char buffer[size][MAXSIZE];
while(fgets(buffer[i], sizeof(buffer[i]), packet)!=NULL){...
char* buffer[size] is an array of N char* pointers which are uninitialized. You must allocate memory to these before using them or your program will explode in a ball of fire.
The fix is to allocate:
for (size_t i = 0; i < size; ++i) {
buffer[i] = malloc(PKT_SIZE);
}
You're going to be responsible for that memory going forward, too, so don't forget to free later.
Allocating an arbitrary number of buffers is pretty wasteful. It's usually better to use some kind of simple linked-list type structure and append chunks as necessary. This avoids pointless over-allocation of memory.
Switching to C from Java, and I'm having some troubles grasping memory management
Say I have a function *check_malloc that behaves as such:
// Checks if malloc() succeeds.
void *check_malloc(size_t amount){
void *tpt;
/* Allocates a memory block in amount bytes. */
tpt = malloc( amount );
/* Checks if it was successful. */
if ( tpt == NULL ){
fprintf(stderr, "No memory of %lu bytes\n", amount);
exit(1);
}
return tpt;
}
I also have the following variables to work with:
FILE *f = fopen("abc.txt", "r"); // Pointer to a file with "mynameisbob" on the first line and
// "123456789" on the second line
char *pname; // Pointer to a string for storing the name
}
My goal is to use *check_malloc to dynamically allocate memory so that the String pointed to by *pname is just the correct size for storing "mynamisbob", which is the only thing on the first line of the text file.
Here is my (failed) attempt:
int main(int argc, char *argv[]){
FILE *f = fopen("abc.txt", "r"); // A file with "mynameisbob" on the first line and
// "123456789" on the second line
char *pname; // Pointer to a string for storing the name
char currentline[150]; // Char array for storing current line of file
while(!feof(f)){
fgets(currentline,100,f);
pname = ¤tline;
}
But I know this probably isn't the way to go about this, because I need to use my nice check_malloc* function.
Additionally, in my actual text file there is a "<" symbol before the name on the first line.But I just want the *pname to point to a String saying "mynameisbob" without the "<" symbol. This isn't that important now, it just is reinforcement to me that I know I can't just set the pointer to point straight to currentline.
Can anyone help me fix my thinking on this one? Thanks a lot.
In C you need to copy chars, not the "strings" (which are just pointers). Check out strcpy() and strlen(). Use strlen() to determine how long the line actually is which fgets has read, then use your malloc() to allocate exactly that (plus 1 for the 0). Then copy the chars over with strcpy().
There are several problems in your code, see my comments in this example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Checks if malloc() succeeds.
void *check_malloc (size_t amount) {
void *tpt;
/* Allocates a memory block in amount bytes. */
tpt = malloc( amount );
/* Checks if it was successful. */
if (tpt == NULL) {
fprintf (stderr, "No memory of %lu bytes\n", amount);
exit (EXIT_FAILURE);
}
return tpt;
}
// To avoid subtle errors I have defined buffer size here
#define BUFFER_SIZE 150
// I have used the (void) version of main () here, while not strictly neccessary, you where not using argc and argv anyway, so the can be left out in this case
int main (void) {
// It might be a good idea to make the filename a char[] as well, but I leave that as an exercise to the reader.
FILE *f = fopen("abc.txt", "r"); // A file with "mynameisbob" on the first line and
// "123456789" on the second line
// You have to check whether the file was *actually openend*
if (f == NULL) {
fprintf (stderr, "Could not open file abc.txt\n"); // '"...%s\n", filename);' might better.
exit (EXIT_FAILURE);
}
char *pname; // Pointer to a string for storing the name
char currentline[BUFFER_SIZE]; // Char array for storing current line of file
while(!feof (f)) {
char *res = fgets (currentline, BUFFER_SIZE, f);
// fgets returns NULL when EOF was encountered before the next '\n'
if (res) {
size_t read = strlen (res);
// The line might have been empty
if (read) {
// Better use "sizeof *varname", while char is always 1 byte it is a good practice
pname = check_malloc ((read + 1) * sizeof *pname); // + 1 because we have to provide an extra char für '\0'
strncpy (pname, currentline, read); // You have to use strcpy or strncpy to copy the contents of the string rather than just assigning the pointer
// What was allocated must be freed again
free (pname);
}
}
}
fclose(f); // Always close everything you open!
return EXIT_SUCCESS;
}
Actually you really don't have to use pname in this simple case, because currentline already contains the line, but since you're trying to learn about memory management this should give you a general idea of how things work.
In your code you had this line:
pname = ¤tline;
There are two problems here:
As already mentioned in my code assigning currentline to pname only copies the pointer not the contents.
The correct assignment would be pname = currentline (without the address operator &), because currentline is also a pointer under the hood (it behaves like char *currentline even though it's statically allocated).
Right now, I'm working on an example code that I wish to integrate into my program later. What essentially I'm trying to do is read a .dat file byte by byte and interpret the data (ie. interpret boot sector to output the sector size, reserved sectors etc.)
To do this, I am reading the data byte by byte and, using the descriptions in fat12 of https://www.win.tue.nl/~aeb/linux/fs/fat/fat-1.html#ss1.3 , I translate the data into the information that I want. Right now, I can pull individual bytes from the file (Is it right to assume that the data pulled is in hex?). However, I need two bytes to have something meaningful. So, I need to combine two bytes into one, convert the hex data into decimal and output the information. Unfortunately, right now, I'm getting a seg fault and for the life of me, I can't figure out what's wrong. Thanks in advance!
int main (int argc, char **argv){
FILE *fp ,*fptest;
long lSize;
char *buffer;
//Open file
fptest= open("fat_volume.dat", "rb");
//Read file into buffer
fread(buffer,1,512,fptest);
//Parse the boot sector
char tmpA, tmpB;
tmpA = buffer[10]; //First byte
tmpB = buffer[11]; //Second byte
//Combine the two bytes into one
char combinedBytes[3];
strcpy (combinedBytes, tmpA);
strcat (combinedBytes, tmpB);
//Hex to decimal converter
long int li1;
li1 = strtol (combinedBytes,NULL,16);
printf ("The sector size is: %ld.\n", li1);
return 0;
}
You must allocate buffer; e.g.
char buffer[512];
or
char *buffer = malloc(512);
EDIT:
The string operations
strcpy (combinedBytes, tmpA);
strcat (combinedBytes, tmpB);
do not make sense either and access/copy too much data (the compiler will warn you about this!).
I suggest do read values as
unsigned char tmpA = buffer[10];
unsigned char tmpB = buffer[11];
unsigned int tmp = (tmpA << 8) | (tmpB << 0); /* or revert in in case of
little-endian */
To make things more efficient, I would write it as
struct fat_header {
uint8_t pad0[10];
uint16_t my_val;
uint8_t pad1[500];
} __attribute__((__packed__)); /* this is not portable and for gcc! */
...
struct fat_header hdr;
fread(&hdr, 1, sizeof hdr, f);
uint16_t val = be16toh(hdr.my_val); /* or le16toh() in case of le */
You are reading into a buffer you never allocated memory for.
What you're trying now is to read from some junk value in memory, who knows, which almost always leads to a segmentation fault.
Use:
char *buffer = malloc(512 * sizeof(char)); // this allocates 512 times the size of a single char of memory
If you don't specify the number inside malloc to be of a specific size (e.g. malloc(512) the number is in bytes, though I think it's better to always include it.
This specific error is called dereferencing a null pointer
EDIT:
I've managed to run this code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char **argv)
{
FILE *fp ,*fptest;
long lSize;
char *buffer;
//Open file
fptest = fopen("input.txt", "rb");
if (fptest == NULL)
{
printf("Error occurred when opening file");
return 1;
}
buffer = malloc(sizeof(char) * 512);
//Read file into buffer
fread(buffer,1,512,fptest);
//Parse the boot sector
char tmpA, tmpB;
tmpA = buffer[10]; //First byte
tmpB = buffer[11]; //Second byte
//Combine the two bytes into one
char combinedBytes[3];
strcpy (combinedBytes, &tmpA);
strcat (combinedBytes, &tmpB);
//Hex to decimal converter
long int li1;
li1 = strtol (combinedBytes,NULL,16);
printf ("The sector size is: %ld.\n", li1);
return 0;
}
You also used a function open() which must be fopen(), and you need to pass the address of tmpA and tmpB to strcpy and strcat.
This is why I don't understand why your compiler doesn't give any errors or warnings..
I have a file of strings seperated by space and I want to get those strings into an array of defined type but I get an error saying that fscanf doesn't take char**, does anyone know how to do this please?
typedef struct{
char *string;
int name;
} DBZ;
DBZ Table[100];
fp = fopen("text.txt", "r");
if(fp == NULL)
{
fprintf(stderr, "Error opening file.");
exit(1);
}
else {
int i=0;
while(!feof(fp))
{
fscanf(fp,"%s", &Table[i].string);
i++;
}
}
&Table[i].string
You're taking an address of a pointer, which is a pointer-of-a-pointer, which is a char**
Also,
fscanf provides no functionality to allocate the memory you need. You'll have to malloc a block large enough to hold whats in your file. Then you'll want to use something safer than fscanf, preferable the most secure thing available* to make sure you don't overwrite the buffer.
else {
int i=0;
while(!feof(fp))
{
Table[i].string = malloc(100);
fscanf_s(fp,"%s", Table[i].string, 100);
i++;
}
}
* These are Microsoft extensions, your platform may have something different.
You need to allocate space for char *string in your struct. And your %s takes char* not char**
Remove the &, Table[i].string is already a pointer.
string also needs to contain memory. You could change the definition of your struct to:
typedef struct{
char string[90];
int name;
} DBZ;
That assumes that your data will fit in 90 bytes. Depending on what your data is, it could also be a very inefficient way of storing it. malloc(), as others have pointed out, could help you here.