Segmentation fault when releasing a string in C - c

I have a "segmentation fault" error when I try to free the allocated memory of the string pointed from "new_job->jobs_adress" . I've allocated enough memory for my string (even if I allocate far beyond from what I need, I still have this problem), But there is still this error.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct job_t {
pid_t pid;
time_t creation_time;
bool stop;
bool foreground;
char * jobs_adress;
} Job;
int main() {
char * jobs_adress = "string";
/* creating an object of "Job" Type */
printf("another try");
Job * new_job = (Job*)malloc(sizeof(new_job));
if(!new_job) {
return;
}
/* allocating memory for a new string, and copies the old string
into the new string*/
int length2=strlen(jobs_adress);
char * str2 = malloc(length2+1);
strcpy(str2,jobs_adress);
new_job->jobs_adress=str2;
new_job->pid = 1;
new_job->creation_time = time(NULL);
new_job->stop=false;
new_job->foreground=true;
free(new_job->jobs_adress); // <=== the error is here
}

Job * new_job = (Job*)malloc(sizeof(new_job));
On this line, sizeof(new_job) is measuring the size of variable new_job.
new_job has type Pointer, and a pointer is (typically) 4 bytes.
So you allocate 4 bytes.
You intended to allocate enough space for a Job struct.
The line should've been:
Job * new_job = (Job*)malloc(sizeof(Job));

Related

Why is there a segmentation fault in strcpy after initializing a struct?

I can't seem to figure out why strcpy makes a segmentation fault in this code. It should be straightforward:
typedef struct message {
char *buffer;
int length;
} message_t;
int main () {
char* buf = "The use of COBOL cripples the mind; its "
"teaching should, therefore, be regarded as a criminal "
"offense. -- Edsgar Dijkstra";
message_t messageA = {"", 130};
message_t *message = &messageA;
strcpy(message->buffer, "buf");
printf("Hello\n");
}
EDIT: strcpy(message->buffer, "buf") is supposed to be strcpy(message->buffer, buf) without the "" quotes
EDIT: Thank you to the comments! This has been resolved by malloc'ing message->buffer to make space for buf:
message_t messageA = {"", 130};
message_t *message = &messageA;
message->buffer = malloc(122);
strcpy(message->buffer, buf);
printf("Hello\n");
some points to be noted here.
when you declare pointers to store data you either assign directly at the declaration (usually used for small strings not big strings) or you should allocate memory using
dynamic memory allocation functions
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct message {
char *buffer;
int length;
} message_t;
int main () {
char* buf = "The use of COBOL cripples the mind; its "
"teaching should, therefore, be regarded as a criminal "
"offense. -- Edsgar Dijkstra";
message_t messageA = {"", 130};
message_t *message = &messageA;
//allocate memory to buffer length of buf, + 1 for \0 character
message->buffer = malloc( strlen(buf) + 1 );
// check allocated memory is success or not
if ( message->buffer )
{
strcpy(message->buffer, buf);
printf("buffer = %s\n",message->buffer );
//free the malloc'ed memory to avoid memory leaks
free(message->buffer);
//make the pointer NULL, to avoid dangling pointer
message->buffer = NULL;
}
else
{
printf("malloc failed\n");
}
printf("Hello\n");
return 0;
}
message_t messageA = {"", 130};
Here, you initializing messageA.buffer = "". It is a string literal. So, you cannot modify the string stored in it. If you try to modify it, you will get segmentation fault.
message_t *message = &messageA;
strcpy(message->buffer, buf);
Here, you are modifying the string literal message->buffer. That's why you got segmentation fault.
Please visit this question Modifying a string literal
Try using message->buffer = strdup(buf); that does the malloc and strlen computation for you.

Declaring/using char pointer inside a struct in c and taking input in it

I am declaring a pointer to a character inside struct, and then taking input from user to store a string in that char pointer, but getting an error,please help
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct arr
{
char *str;
int len;
} s1;
int main()
{
scanf("%s", s1.str);
s1.len = strlen(s1.str);
printf("%d", s1.len);
}
A char* is not enough to store a string, as a char* points to a string.
You need memory space to store the string itself.
Example:
struct arr
{
char str[128]; // will store strings up to 127 bytes long, plus the ending nul byte.
int len;
} s1;
int main()
{
scanf("%127s", s1.str);
s1.len = strlen(s1.str);
printf("%d", s1.len);
}
Dynamic memory allocation
In main function :
s1 *p = (s1 *)malloc(sizeof(s1));
if ( p == NULL )
{
printf("Memory allocation failed \n")
exit (0);
}
p->str = (char*)malloc(sizeof(char)*256); // here 256 bytes allocated
if (p->str)
{
printf("Memory allocation failed \n")
exit (0);
}
Then use :
free(p)
To free the memory previously allocated.

Invalid read of Size 1 when mallocing large String

I have a unique case where I'm trying to store a 4096 character string in a struct member. However, I'm mallocing the usually amount of memory for a shorter string, but am still getting a valgrind error:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct List {
char * name;
int grade;
struct List * next;
};
int main(void) {
struct List * newList;
char * bigString;
int i;
bigString = malloc(sizeof(char)* 4096);
for (i=0; i<4096; i++)
bigString[i] = 'a';
newList = malloc(sizeof(struct List));
newList->next = NULL;
newList->name = malloc(strlen(bigString)+1);
free(bigString);
free(newList->name);
free(newList);
return 0;
}
the line:
newList->name = malloc(strlen(bigString)+1);
Returns an error Invalid read of size 1
But wait a second, I'm mallocing the lenght of the string, plus 1 for the null terminator, what's going on here?
In fact I even tried this:
newList->name = malloc(sizeof(char) * strlen(bigString) +1);
And heck I even tried to null terminate the string after the malloc call:
newList->name[strlen(bigString)] = '\0';
To no avail..
I'm actually beyond confused as to what I've done wrong here. Any ideas?
bigString itself is not null-terminated, so strlen(bigString) results in trying to read past the end of the space allocated for bigString.
You forgot to add a \0 at the end of BigString.

pointer being freed was not allocated in C

Not sure what is wrong with the code below and why it is giving me the error "pointer being freed was not allocated". Using clang.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
static char * messagePtr;
int main()
{
messagePtr = (char *)malloc(sizeof(char) * 800);
if(messagePtr == NULL) {
printf("Bad malloc error\n");
exit(1);
}
// //gameLoop();
char outputMessage[50] = "";
messagePtr = outputMessage;
free(messagePtr);
messagePtr = NULL;
return 0;
}
You assigned outputMessage, which is an array and is converted to a pointer to the first element of the array, to messagePtr, so messagePtr no longer points at what is allcated via malloc() or its family.
Passing what is not NULL and is not allocated via memory management functions such as malloc() invokes undefined behavior. (N1570 7.22.3.3 The free function)
Note that they say you shouldn't cast the result of malloc() in C.
Some of your options are:
1. Stop using malloc() for allocating buffer that will be thrown away.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
static char * messagePtr;
int main()
{
// //gameLoop();
char outputMessage[50] = "";
messagePtr = outputMessage;
messagePtr = NULL;
return 0;
}
2. Free the buffer before throwing it away.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
static char * messagePtr;
int main()
{
messagePtr = malloc(sizeof(char) * 800);
if(messagePtr == NULL) {
printf("Bad malloc error\n");
exit(1);
}
// //gameLoop();
free(messagePtr);
char outputMessage[50] = "";
messagePtr = outputMessage;
messagePtr = NULL;
return 0;
}
3. Use strcpy() to copy strings.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
static char * messagePtr;
int main()
{
messagePtr = malloc(sizeof(char) * 800);
if(messagePtr == NULL) {
printf("Bad malloc error\n");
exit(1);
}
// //gameLoop();
char outputMessage[50] = "";
strcpy(messagePtr, outputMessage);
free(messagePtr);
messagePtr = NULL;
return 0;
}
The lines
char outputMessage[50] = "";
messagePtr = outputMessage;
create a char[50] and assign messagePtr the address of that array, thus removing the pointer to the malloced memory. The successive free call therefore tries to free messagePtr, not the memory allocated by malloc. Not only this, the mallocated memory will be lost since you have lost all reference (i.e., the pointer) to it.
I'm not entirely sure what you are trying to accomplish by messagePtr = outputMessage, so I can't really give you a hint on solving this - except to not reassign a pointer returned by malloc prior to freeing it.
Notes:
You do not need to cast void*, as returned by malloc, to other pointer types. There is an implicit conversion for that. Read why not to cast the return value of malloc.
messagePtr = (char *)malloc(sizeof(char) * 800);
makes messagePtr pointing to the location in Heap where malloc allocated 800 chars (e.g. 1005). This location has to be freed.
messagePtr = outputMessage;
makes messagePtr pointing to the location in Stack where 50 chars where automatically allocated (e.g. 505).
Automatic allocations can not be freed with free. They are deallocated automatically when the variable's scope ends.
Calling free on the automatically allocated memory is an error. free has to be called on location 1005 (according to the example).

Change string with malloc in other function

how can I change string in other function when I am using malloc?
in main:
char *myString;
changeString(myString);
changeString(char *myString){
myString = malloc((size) * sizeof(char));
myString[1] = 'a';
}
Thank you
Parameters in C are passed by value. So to modify a variable within a function, you'll have to pass the pointer to it. For example, int * to int, and char ** to char *.
void changeString(char **myString){
// free(*myString); // add when myString is allocated using malloc()
*myString = malloc(2);
(*myString)[0] = 'a';
(*myString)[1] = '\0';
}
Allocate memory in main, then pass a pointer to start of allocated memory to the function.
Also pass a variable containing the size of the allocated memory to the function, so that you can ensure that the new text does not overflow the allocated memory.
The modified string is available from main.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void changeString(char *stringptr, int sz);
int main(void)
{
const int a_sz = 16;
/* allocate memory for string & test successful allocation*/
char *myString = malloc(a_sz);
if (myString == NULL) {
printf("Out of memory!\n");
return(1);
}
/* put some initial characters into String */
strcpy(myString, "Nonsense");
/* print the original */
printf("Old text: %s\n", myString);
/* call function that will change the string */
changeString(myString, a_sz);
/* print out the modified string */
printf("New text: %s\n", myString);
/* free the memory allocated */
free(myString);
}
void changeString(char *stringptr, int sz)
{
/* text to copy into array */
char *tocopy = "Sense";
/* only copy text if it fits in allocated memory
including one byte for a null terminator */
if (strlen(tocopy) + 1 <= sz) {
strcpy(stringptr, tocopy);
}
}

Resources