I am getting Segmentation error(core dump) in the following code:
void Update_Log( )
{
struct logData update;
int file;
char *writeBuffer=NULL;
if((file=creat("/home/user/Desktop/DMS/DMS/filename.txt",O_RDONLY|O_WRONLY))==-1)
perror("file not opened");
update.clientName="user";
update.filename="user";
update.timestamp="some time";
sprintf(writeBuffer,"%s %s %s",update.clientName,update.filename,update.timestamp);
if((write(file,writeBuffer,sizeof(writeBuffer)))==-1)
perror("write unsuccessful");
close(file);
}
My structure is as follows:
struct logData
{
char *clientName;
char *filename;
char *timestamp;
};
Can anyone help in this?
You're trying to write to writeBuffer which is a null pointer, you should declare it as array(1), or allocate a memory on the heap(2) for it.
char writeBuffer[100];
char *writeBuffer=malloc(100)
in both cases you should not use sprintf, but snprintf to make sure you are not overflowing your buffer.
When 'update' is created it only allocates the space for the pointers of the strings clientName, filename, timestamp; it does not allocate space for the string itself. A quick hack would be to do something like update.clientName = (char*)malloc(sizeof(char)*len) where len is the length of what you want to allocate. Then you should really check the return code of that call...
This is exactly the same issue as with the write buffer... you just need to make sure you allocate space for all your strings.
The error is these two lines:
char *writeBuffer=NULL;
/* ... */
sprintf(writeBuffer, /* ... */);
Here you write into a NULL pointer.
Create an array instead, e.g.
char writeBuffer[32];
You need to allocate space for writeBuffer.
You could use malloc, or if you have limits on the size of the data (eg if it will be less than 256 bytes) just declare it as
char writeBuffer[256];
I'd also recommend looking up and using snprintf instead of sprintf to make sure data doesnt run off the end.
your struct store only pointers, no memory is allocated for the actual data.
Either you should have
struct logData
{
char clientName[SOMEDEFINE1NUMBERHERE];
char filename[SOMEDEFINE2NUMBERHERE];
char timestamp[SOMEDEFINE3NUMBERHERE];
};
or you allocate the memory (malloc)
update.clientname = (char *)malloc(SOMEDEFINE1NUMBERHERE);
strncpy(update.clientname, "user");
As Binyamin Sharet wrote sprintf is not allocating the output buffer. The caller must provide an output buffer that is long enough. This is not always simple. Therefor I advise you to use fopen instead of open. Then you can code like that:
void Update_Log( )
{
struct logData update;
FILE *file = fopen("/home/user/Desktop/DMS/DMS/filename.txt", "w");
if(file==NULL) {
perror("file not opened");
return;
}
update.clientName="user";
update.filename="user";
update.timestamp="some time";
if(fprintf(file,"%s %s %s",update.clientName,update.filename,update.timestamp) < 0)
perror("write unsuccessful");
fclose(file);
}
As you can see the code is shorter and it has no potential buffer overflow.
It crashes, because writeBuffer is NULL.
You need to allocate memory for writeBuffer using malloc - use strlen (for example) to calculate the neccesary space (don't forget \0 and the spaces in the sprintf).
OR, you may allocate some fixed size array automatically:
char writeBuffer[ SOME_SIZE_BIG_ENOUGH ];
Also, you should not do this:
update.clientName="user";
update.filename="user";
update.timestamp="some time";
You have several options:
use strcpy
use strdup (POSSIX)
make the pointers const char*, not just char*.
Related
It's not clear to me what's wrong with my program, it's a simple code to open a file, read the first line from it, and then print it. But the program keeps crashing. The actual content of my text file is a sentence: Test my code.
int main(void)
{
FILE *stream;
char *s;
stream = fopen("input.txt", "r");
fscanf(stream, " %s", &s);
printf("%s", s);
fclose(stream);
return 0;
}
I'm instructed not to use the library functions found in <string.h>
s is an uninitialized pointer. You need to allocate some memory for fscanf to write into.
char *s;
Allocates the number of bytes needed for holding a memory address (on most systems 32/64 bits).
But since you are not initializing the pointer, its value (the address it points to) is undefined.
Ergo: fscanf tries to write to an undefined memory address.
I initialized it as char *s = NULL;
Yes, the pointer is now initialized (yay!) but now points to nowhere.
Ergo: fscanf will try to write to nothing.
The solution is to allocate some memory fscanf can use.
fscanf does not magically allocate memory for you!
You can use either stack memory or dynamic allocated memory (heap).
Stack memory is easier to manage but is much smaller than the heap.
Here a solution which uses memory on the stack:
// Allocates 10 bytes on the stack
// Given 1 Character = 1 Byte the
// buffer can hold up to 9 characters.
char myBuffer[10];
// Initialize s with the address of myBuffer
char *s = myBuffer;
// Call fscanf
fscanf(stream, "%9s", s);
You may be wondering why I used %9s instead of %s.
The reason is to prevent a buffer overflow:
fscanf does not know how big the buffer is, so you need to tell it.
Otherwise fscanf will write data beyond your allocated memory.
I suggest you read up on C strings and memory management in general.
There are few things you are missing in your code.
// Uninitialise pointer, you need to allocate memory dynamically with malloc before you use it. That is
char *s;
int size = 20; // size of the string you want
s = malloc(size * sizeof(char));
// Or you can use a VLA and with this you don't have to use free(s)
char s[20];
// fopen could fail, always check the return value before using it.
stream = fopen("input.txt", "r");
if(stream == NULL){
perror("File opening failed");
return EXIT_FAILURE;
}
fscanf(stream, "%s", s);
//Don't forget to do free(s) to free memory allocated with malloc . when you are done with it
Having some issues comparing char arrays thru pointers. I am working without both the string library and iostream, would like to keep it that way.
char *GetCurrentPath()
{
char buffer[MAX_PATH];
if (!GetModuleFileNameA(NULL, buffer, MAX_PATH)) {
printf("GetModuleFileNameA failed, error: %d\n", GetLastError());
}
return (buffer);
}
char *GetInstallPath()
{
char buffer[MAX_PATH];
if (!SHGetSpecialFolderPathA(NULL, buffer, CSIDL_APPDATA, FALSE)) {
printf("SHGetSpecialFolderPathA failed, error: %d\n", GetLastError());
}
strcat(buffer, "\\service.exe");
return (buffer);
}
char *InstallPath = GetInstallPath();
char *CurrentPath = GetCurrentPath();
if (InstallPath == CurrentPath)......
The if statement causes an instant crash, same goes for strcomp.
Suggestions?
What you are currently doing is undefined behavior. The buffers that you are using in the two functions are defined locally to those functions and go out of scope the moment the functions end, giving you pointers to random stack addresses.
You need to either allocate the buffers in the functions:
Replace : char buffer[MAX_PATH];
With: char *buffer = new char[MAX_PATH]
Or pass allocated buffers from your main to the functions:
char *InstallPath = new char[MAX_PATH];
GetInstallPath(InstallPath);
And change your get path functions:
char *GetInstallPath(char *buffer)
In both cases, you will have to delete your pointers before ending your program to free up the memory.
On top of that, when you try to compare the two variables, they will compare pointer addresses rather than string contents. You will need to use strcmp() or something in that family of functions.
Your functions return an array (char *) declared locally inside them. Your pointers have undefined values outside the functions. You can't do that.
You may allocate them dynamically:
char *buffer = malloc(MAX_PATH*sizeof(char));
Since both buffers are allocated on stack, they are freed after the function execution ends. So, the pointers function returns becomes invalid.
To fix that, you have to allocate buffer[] on heap, using char * buffer = new char[MAX_PATH];
But after you will have to free the memory manually.
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).
while(!feof(fname))
{
fscanf(fname,"%c",buf);
printf("%c",*buf);
buf++;
}
When I use this code, the compiler gives me a segmentation fault(core dumped).
But instead of this if I use
int i = 0;
while(!feof(fname))
{
fscanf(fname,"%c",&buf[i]);
printf("%c",buf[i]);
i++;
}
This code runs fine, and the content of the file are read.
What am I doing wrong while incrementing the array pointer instead of using it as and array?
The whole code is
FILE *fname;
fname = fopen("input.txt", "r");
int i;
char *buf;
i=0;
while(!feof(fname))
{
fscanf(fname,"%c",buf);
printf("%c",*buf);
buf++;
}
fclose(fname);
char *buf;
This is a pointer and has no memory associated with it.
fscanf(fname,"%c",buf);
is attempting to place memory into this pointer. It needs to either be malloc'd, or defined as a char array that won't overflow from the fscanf() input.
perhaps:
#define MAX_STRING_SIZE 255
char buf[MAX_STRING_SIZE];
Additional Info edit
If you need a moving pointer, create a second one and use it:
#define MAX_STRING_SIZE 255
char buffer_memory[MAX_STRING_SIZE];
char *buf = buffer_memory;
...
fscanf(fname,"%c",buf);
printf("%c",*buf);
buf++;
Until you read in 255 character at which point bad things happen. If you don't know how big your file is beforehand (ftell()), then you will need to use a linked list system, a realloc() pattern, which is kinda icky, or a buffer that is guarenteed to be big enough to fit your file.
I am trying to copy a string into another char pointer variable using strcpy function.But I always get segmentation fault.Here is my code.
/* strcat example */
#include <stdio.h>
#include <string.h>
int main()
{
char str[100]="";
char *pch3;
strcpy(pch3,"Ravi");
//strcat(str,pch3); //Segmnetation fault.
puts(pch3);
return 0;
}
If I do the same thing in this one I still get segmentation fault.
else
{
misc_rec_cnt++;
fp1=fopen("breast-cancer-wisconsin-miscellaneous.data","a");
fprintf(fp1,"%s",line2);
fclose(fp1);
fp2=fopen("missingSCNs.data","a");
pch2=strtok(line2,",");
fprintf(fp2,"%s\n",pch2);
fclose(fp2);
//pch3=(char *)malloc(sizeof(char)*strlen(line3));
pch3 = strtok(line3,",");
while(pch3!=NULL)
{
if(strcmp(pch3,"?") == 0)
{
strcat(str1,"0");
strcat(str1,",");
}
else
{
//strcat(str1,pch3);
strcat(str1,",");
}
pch3 = strtok(NULL,",");
}
strlen1=strlen(str1);
memcpy(str2,str1,strlen1-1);
fp3=fopen("breast-cancer-wisconsin-miscellaneous-cleansed.data","a");
fprintf(fp3,"%s\n",str2);
fclose(fp3);
}
You need to allocate the space for pch3 before you copy to it. Use malloc to create a char array large enough to accomodate the elements of your source string before you copy it. What you are currently doing is declaring a char pointer and not initialising it. Therefore the memory location that it points to could be anywhere - and that means that you should probably not be attempting to write to it - which is why you are getting the segfault. Using malloc will allow you to allocate a region of memory that you are safe to write to and this will solve your problem (assuming the call to malloc succeeds). You cannot just go writing data to random memory locations without getting segfaults and access violations.
pch3 is a char pointer, but it doesn't have any storage associated with it which is the cause of the problem. Call malloc() to allocate some memory that the pch3 pointer can point to and you should be ok.
At this point you have a char pointer that is uninitialized and just pointing somewhere unknown. So try this:
pch3 = (char *)malloc(sizeof(char) * 100); /* 100 just as an example */
This tutorial might be helpful or this SO question: Allocating char array using malloc
pch3 is an unallocated pointer, so you're writing data to a location that doesn't exist. Did you mean to assign it to str?
char str[100]="";
char *pch3;
pch3 = str;
strcpy(pch3,"Ravi");
I'd recommend that you first allocate memory before copying data to a random place.
strcpy(pch3=(char*)malloc(sizeof("Ravi")),"Ravi");
but better check if it didn't return null pointer.