Joseph Seung Jae Dollar
Joseph Seung Jae Dollar

Reputation: 1076

Bus error caused while reading in a string

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main() {
	char *input = (char *)malloc(sizeof(char));
	input = "\0";

	while (1){
		scanf("%s\n", input);

		if (strcmp(input, "0 0 0") == 0) break;

		printf("%s\n",input);
	}

}

I'm trying to read in a string of integers until "0 0 0" is entered in. The program spits out bus error as soon as it executes the scanf line, and I have no clue how to fix it. Below is the error log.

[1]    59443 bus error

Upvotes: 0

Views: 770

Answers (3)

fukanchik
fukanchik

Reputation: 2865

input = "\0";

is wrong.

'input' is pointer, not memory.

"\0" is string, not char.

You assigning pointer to a new value which points to a segment of memory which holds constants because "\0" is constant string literal.

Now when you are trying to modify this constant memory, you are getting bus error which is expected.

In your case i assume you wanted to initialize 'input' with empty string. Use

input[0]='\0';

note single quotes around 0.

Next problem is malloc:

char *input = (char *)malloc(sizeof(char));

you are allocating memory for 1 character only.

When user will enter "0 0 0" which is 5 characters + zero you will get buffer overflow and will probably corrupt some innocent variable.

Allocate enough memory upfront to store all user input. Usual values are 256, 8192 bytes it doesn't matter.

Then,

scanf("%s\n", input);

may still overrun the buffer if user enters alot of text. Use fgets(buf, limit(like 8192), stdin), that would be safer.

Upvotes: 0

juanchopanza
juanchopanza

Reputation: 227468

You set input to point to the first element of a string literal (while leaking the recently allocated buffer):

input = "\0"; // now the malloc'd buffer is lost

Then you try to modify said literal:

scanf("%s\n", input);

That is undefined behaviour. You can't write to that location. You can fix that problem by removing the first line, input = "\0";.

Next, note that you're only allocating space for one character:

char *input = (char *)malloc(sizeof(char));

Once you fix the memory leak and the undefined behaviour, you can think about allocating more space. How much space you need is for you to say, but you need enough to contain the longest string you want to read in plus an extra character for the null terminator. For example,

char *input = malloc(257);

would allow you to read in strings up to 256 characters long.

Upvotes: 4

BaseZen
BaseZen

Reputation: 8718

The immediate problem, (thanks to another answer) is that you're initializing input wrong, by pointing it at read-only data, then later trying to write to it via scanf. (Yes, even the lowly literal "" is a pointer to a memory area where the empty string is stored.)

The next problem is semantic: there's no point in trying to initialize it when scanf() will soon overwrite whatever you put there. But if you wanted to, a valid way is input[0] = '\0', which would be appropriate for, say, a loop using strcat().

And finally, waiting in the wings to bite you is a deeper issue: You need to understand malloc() and sizeof() better. You're only allocating enough space for one character, then overrunning the 1-char buffer with a string of arbitrary length (up to the maximum that your terminal will allow on a line.)

A rough cut would be to allocate far more, say 256 chars, than you'll ever need, but scanf is an awful function for this reason -- makes buffer overruns painfully easy especially for novices. I'll leave it to others to suggest alternatives.

Interestingly, the type of crash can indicate something about what you did wrong. A Bus error often relates to modifying read-only memory (which is still a mapped page), such as you're trying to do, but a Segmentation Violation often indicates overrunning a buffer of a writable memory range, by hitting an unmapped page.

Upvotes: 0

Related Questions