Segmentation Fault using when while loop - c

I am writing a program which take a line from user and invert case of letters
The following code works fine
#define _GNU_SOURCE
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
int main(void) {
printf("Enter line: ");
char *input_ptr;
size_t input_length;
ssize_t read = (int) getline(&input_ptr, (void *) (&input_length), stdin);
if (read != -1) {
int i = 0;
for (; i < input_length; i++) {
int c = *(input_ptr + i);
if (isupper(c)) {
printf("%c", tolower(c));
} else {
printf("%c", toupper(c));
}
}
} else {
puts("Something Wrong Happened ...");
}
return 0;
}
However, when I change the for loop to while loop:
#define _GNU_SOURCE
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
int main(void) {
printf("Enter line: ");
char *input_ptr;
size_t input_length;
ssize_t read = (int) getline(&input_ptr, (void *) (&input_length), stdin);
if (read != -1) {
while (*input_ptr != '\0') {
int c = *input_ptr;
input_ptr++;
if (isupper(c)) {
printf("%c", tolower(c));
} else {
printf("%c", toupper(c));
}
}
} else {
puts("Something Wrong Happened ...");
}
return 0;
}
It says segmentation error after I have entered my line.
May I know what happened? Thanks in advance.

You have not initialised input_ptr so the code has undefined behaviour. You might have passed an invalid buffer address to getline. You should also initialise input_length, so
char *input_ptr = NULL;
size_t input_length = 0;
The function getline() expects either a pointer to memory you allocated yourself, or NULL to indicate that the function should allocate memory.
If *lineptr is set to NULL and *n is set 0 before the call, then getline() will allocate a buffer for storing the line. This buffer should be freed by the user program even if getline() failed.
Note, you should not increment a pointer which you intend to free later.

Related

Why doesn't the code run with a test.in file created by Sublime TextEditor

This was a piece of code I have written for my assignment, some of the weird code design are not controllable by me. I am currently writing these on MacOS.
file1
#include <stdio.h>
extern int read_palindrome();
int main()
{
if (read_palindrome()) printf("input is a palindrome");
else printf("input is not a palindrome");
return 0;
}
file2
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int check_palindrome2(char *, int);
// malloc() will be used as usual to set aside an initial memory
// The entire input will be read gradually by characters using getchar()
// In the event we require more memory than what we have previously,
// use realloc() to increase memory size dynamically
int read_palindrome() {
unsigned int len_max = 128;
unsigned int current_size = 0;
char *pStr = malloc(len_max);
current_size = len_max;
int i = 0;
int c = EOF;
if (pStr == NULL) {
return -1;
}
while (( c = getchar() ) != '\n') {
pStr[i] = (char)c;
i++;
if(i == current_size) {
current_size += len_max;
char *tmp = realloc(pStr, current_size);
if (tmp == NULL) {
free(pStr);
return -1;
}
pStr = tmp;
}
}
int retval = check_palindrome2(pStr,i);
free(pStr);
return retval;
}
int check_palindrome2(char *s, int length) {
for (int i = 0; i < length / 2; i++) {
if (s[i] != s[length-i-1])
return 0;
}
return 1;
}
I would think this code works except for empty files, which will cause my program to continuously expect input and not terminate. However, I realised when using Sublime Text, creating a test.in file without pressing "Enter" somehow displays the "non-terminating" behaviour as well, while typing something in vim without pressing "Enter" for a newline still allows the code to work. Does anyone know the reason behind this phenomenon?

segmentation fault in c about using malloc, and char array pointer

im trying to make a program which reads what we wrote without concerning the memory, and print out what we wrote!
but it goes to segmentation fault (core dump)
#include <stdio.h>
#include <string.h>
int isdigit(char c);
int main()
{
char *input
int length;
printf("Number or Letter\n");
gets(input);
input = (char*)malloc(sizeof(char)*strlen(input));
printf(input[0]);
return 0;
}
To read in an arbitrary long input string, you must use some kind of memory re-allocation when the input string grows beyond the already allocated memory. For instance you could use realloc like this:
#include <stdio.h>
#include <stdlib.h>
#define INCREASE 32
int main(void) {
int c;
int allocated = INCREASE;
int used = 1;
char* in = malloc(allocated*sizeof(char));
if (!in) exit(1);
*in = '\0';
while((c = fgetc(stdin)) != EOF && c != '\n')
{
if (used > (allocated-1))
{
// printf("Realloc\n");
allocated += INCREASE;
char* t = realloc(in, allocated);
if (t)
{
in = t;
}
else
{
free(in);
exit(1);
}
}
in[used-1] = c;
in[used] = '\0';
++used;
}
printf("%s\n", in);
free(in);
return 0;
}

How can i make C program that scans user's input(text) and save it on a dynamic string

I want to read input from user(text) using a C program and here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
int i=0,x=0;
char *c;
c[i]=(char*)malloc(sizeof(char));
while(1){
c[i]=getc(stdin);
if(c[i]=='\n')
break;
i++;
realloc(c, i+1 );
}
c[i]='\0';
//printf("\n%d",strlen(c));
printf("\n\n%s",c);
return 0;
}
This program when it compiles there is 1 warning at c[i]=(char*)malloc(sizeof(char));:
warning: assignment makes integer from pointer without a cast [enabled by default]
This program works succesfully but if i remove x=0 from the code there is:
Segmentation fault (core dumped)
What should i change on this code so it can work without warnings or a useless random variable like x=0 to work.
Thank you!
As said by #Dabo, adjust the assignment.
c = malloc(sizeof(char));
Following are additional suggestions:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
// Use size_t rather than int for index
size_t i=0;
char *c;
c = malloc(1);
if (c == NULL) return 1; // Out of memory
while(1){
// To detect EOF condition, use type `int` for get() result
int ch = getc(stdin);
if(ch == EOF || ch == '\n') {
break;
}
c[i++] = ch;
// Important, test & save new pointer
char *c2 = realloc(c, i+1 );
if (c2 == NULL) return 1; // Out of memory
c = c2;
}
c[i] = '\0';
// Use %zu when printing size_t variables
printf("\n%zu",strlen(c));
printf("\n\n%s",c);
// Good practice to allocated free memory
free(c);
return 0;
}
Edit: fixed
Simply replace this
c[i]=(char*)malloc(sizeof(char));
with this
c = (char*)malloc(sizeof(char));
and remove cast, you don't need it in C.
c = malloc(sizeof(char));
Try this
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
int i=0;
char *c=(char*)malloc(sizeof(char));
while(1){
c[i]=getc(stdin);
if(c[i]=='\n')
break;
i++;
}
c[i]='\0';
printf("\n\n%s",c);
return 0;
}

How to read a line from a read-only FIFO in C?

I've got a problem reading a couple of lines from a read-only FIFO. In particular, I have to read two lines — a number n, followed by a \n and a string str — and my C program should write str in a write-only FIFO for n times. This is my attempt.
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
char *readline(int fd);
int main(int argc, char** argv) {
int in = open(argv[1], O_RDONLY);
mkfifo(argv[2], 0666);
int out = open(argv[2] ,O_WRONLY);
char *line = (char *) malloc(50);
int n;
while (1) {
sscanf(readline(in), "%d", &n);
strcpy(line, readline(in));
int i;
for (i = 0; i < n; i++) {
write(out, line, strlen(line));
write(out, "\n", 1);
}
}
close(in);
close(out);
return 0;
}
char *readline(int fd) {
char *c = (char *) malloc(1);
char line[50];
while (read(fd, c, 1) != 0) {
if (strcmp(c, "\n") == 0) {
break;
}
strcat(line, c);
}
return line;
}
The code is working properly, but it puts a random number of newlines after the last string repetition. Also, this number changes at each execution.
Could someone please give me any help?
Besides the facts that reading character wise and and comparing two characters using "string" comparsion both is far from being efficient, readline() returns a pointer to memory being declared local to readline(), that is line[50] The memory gets deallocated as soon as readline() returns, so accessing it afterwards invokes undefine behaviour.
One possibility to fix this is to declare the buffer to read the line into outside readline() and pass a reference to it down like so:
char * readline(int fd, char * line, size_t size)
{
if ((NULL != line) && (0 < size))
{
char c = 0;
size_t i = 0;
while (read(fd, &c, 1) >0)
{
if ('\n' == c) or (size < i) {
break;
}
line[i] = c;
++i;
}
line [i] = 0;
}
return line;
}
And then call it like this:
char * readline(int fd, char * line, size_t size);
int main(void)
{
...
char line[50] = "";
...
... readline(in, line, sizeof(line) - 1) ...
I have not tried running your code, but in your readline function you have not terminated the line with null ('\0') character. once you hit '\n' character you just breaking the while loop and returning the string line. Try adding '\0' character before returning from the function readline.
Click here for more info.
Your code did not work on my machine, and I'd say you're lucky to get any meaningful results at all.
Here are some problems to consider:
readline returns a locally defined static char buffer (line), which will be destroyed when the function ends and the memory it once occupied will be free to be overwritten by other operations.
If line was not set to null bytes on allocation, strcat would treat its garbage values as characters, and could possibly try to write after its end.
You allocate a 1-byte buffer (c), I suspect, just because you need a char* in read. This is unnecessary (see the code below). What's worse, you do not deallocate it before readline exits, and so it leaks memory.
The while(1) loop would re-read the file and re-print it to the output fifo until the end of time.
You're using some "heavy artillery" - namely, strcat and memory allocation - where there are simpler approaches.
Last, some C standard versions may require that you declare all your variables before using them. See this question.
And here's how I modified your code. Note that, if the second line is longer than 50 characters, this code may also not behave well. There are techniques around the buffer limit, but I don't use any in this example:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
char *readline(int fd, char * buffer);
int main(int argc, char** argv) {
int in = open(argv[1], O_RDONLY);
int out;
int n;
int i;
char line[50];
memset(line, 0, 50);
mkfifo(argv[2], 0666);
out = open(argv[2] ,O_WRONLY);
sscanf(readline(in, line), "%d", &n);
strcpy(line, readline(in, line));
for (i = 0; i < n; i++) {
write(out, line, strlen(line));
write(out, "\n", 1);
}
close(in);
close(out);
return 0;
}
char *readline(int fd, char * buffer) {
char c;
int counter = 0;
while (read(fd, &c, 1) != 0) {
if (c == '\n') {
break;
}
buffer[counter++] = c;
}
return buffer;
}
This works on my box as you described. Compiled with GCC 4.8.2 .

Returning a string to a variable length character array

I have a program that reverses a string from an input of a variable length character array. The function returns a variable length character array and is printed. When I print the output, I do get the reversed string, but there are garbage characters appended to it in my console print.
Is this a "legal" operation in terms of returning to buffers? Can someone please critique my code and suggest a better alternative if it is not the right approach?
Thanks.
#include <stdio.h>
#include <stdlib.h>
char *reverse_string(char *input_string);
char *reverse_string(char *input_string)
{
int i=0;
int j=0;
char *return_string;
char filled_buffer[16];
while (input_string[i]!='\0')
i++;
while (i!=0)
{
filled_buffer[j]=input_string[i-1];
i--;
j++;
}
return_string=filled_buffer;
printf("%s", return_string);
return return_string;
}
int main (void)
{
char *returned_string;
returned_string=reverse_string("tasdflkj");
printf("%s", returned_string);
return 1;
}
This is my output from Xcode - jklfdsat\347\322̲\227\377\231\235
No, it isn't safe to return a pointer to a local string in a function. C won't stop you doing it (though sometimes the compiler will warn you if you ask it to; in this case, the local variable return_string prevents it giving the warning unless you change the code to return filled_buffer;). But it is not safe. Basically, the space gets reused by other functions, and so they merrily trample on what was once a neatly formatted string.
Can you explain this comment in more detail — "No, it isn't safe..."
The local variables (as opposed to string constants) go out of scope when the function returns. Returning a pointer to an out-of-scope variable is undefined behaviour, which is something to be avoided at all costs. When you invoke undefined behaviour, anything can happen — including the program appearing to work — and there are no grounds for complaint, even if the program reformats your hard drive. Further, it is not guaranteed that the same thing will happen on different machines, or even with different versions of the same compiler on your current machine.
Either pass the output buffer to the function, or have the function use malloc() to allocate memory which can be returned to and freed by the calling function.
Pass output buffer to function
#include <stdio.h>
#include <string.h>
int reverse_string(char *input_string, char *buffer, size_t bufsiz);
int reverse_string(char *input_string, char *buffer, size_t bufsiz)
{
size_t j = 0;
size_t i = strlen(input_string);
if (i >= bufsiz)
return -1;
buffer[i] = '\0';
while (i != 0)
{
buffer[j] = input_string[i-1];
i--;
j++;
}
printf("%s\n", buffer);
return 0;
}
int main (void)
{
char buffer[16];
if (reverse_string("tasdflkj", buffer, sizeof(buffer)) == 0)
printf("%s\n", buffer);
return 0;
}
Memory allocation
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *reverse_string(char *input_string);
char *reverse_string(char *input_string)
{
size_t j = 0;
size_t i = strlen(input_string) + 1;
char *string = malloc(i);
if (string != 0)
{
string[--i] = '\0';
while (i != 0)
{
string[j] = input_string[i-1];
i--;
j++;
}
printf("%s\n", string);
}
return string;
}
int main (void)
{
char *buffer = reverse_string("tasdflkj");
if (buffer != 0)
{
printf("%s\n", buffer);
free(buffer);
}
return 0;
}
Note that the sample code includes a newline at the end of each format string; it makes it easier to tell where the ends of the strings are.
This is an alternative main() which shows that the allocated memory returned is OK even after multiple calls to the reverse_string() function (which was modified to take a const char * instead of a plain char * argument, but was otherwise unchanged).
int main (void)
{
const char *strings[4] =
{
"tasdflkj",
"amanaplanacanalpanama",
"tajikistan",
"ablewasiereisawelba",
};
char *reverse[4];
for (int i = 0; i < 4; i++)
{
reverse[i] = reverse_string(strings[i]);
if (reverse[i] != 0)
printf("[%s] reversed [%s]\n", strings[i], reverse[i]);
}
for (int i = 0; i < 4; i++)
{
printf("Still valid: %s\n", reverse[i]);
free(reverse[i]);
}
return 0;
}
Also (as pwny pointed out in his answer before I added this note to mine), you need to make sure your string is null terminated. It still isn't safe to return a pointer to the local string, even though you might not immediately spot the problem with your sample code. This accounts for the garbage at the end of your output.
First, returning a pointer to a local like that isn't safe. The idiom is to receive a pointer to a large enough buffer as a parameter to the function and fill it with the result.
The garbage is probably because you're not null-terminating your result string. Make sure you append '\0' at the end.
EDIT: This is one way you could write your function using idiomatic C.
//buffer must be >= string_length + 1
void reverse_string(char *input_string, char* buffer, size_t string_length)
{
int i = string_length;
int j = 0;
while (i != 0)
{
buffer[j] = input_string[i-1];
i--;
j++;
}
buffer[j] = '\0'; //null-terminate the string
printf("%s", buffer);
}
Then, you call it somewhat like:
#define MAX_LENGTH 16
int main()
{
char* foo = "foo";
size_t length = strlen(foo);
char buffer[MAX_LENGTH];
if(length < MAX_LENGTH)
{
reverse_string(foo, buffer, length);
printf("%s", buffer);
}
else
{
printf("Error, string to reverse is too long");
}
}

Resources