Function to calculate string length; I think the logic here is correct:
int strlength(char *s)
{
int count=0;
while(*s!='\0')
{
count++;
s++;
}
return count;
}
int main(void) {
char *s;
int length;
printf("enter your string ");
scanf("%s",s);
length = strlength(s);
printf("string length:%d",length);
return 0;
}
Am I taking the string correctly here and assigning it? Can anyone please explain why I get segmentation fault here?
Your s has to point to something. Here is an example of allocating 128 bytes:
s = malloc(128);
Be sure to release the memory once you're done with it:
free(s);
Note that you must limit how much can be read from the user.
scanf("%127s", s);
I've left an extra byte for the NUL terminator.
this second line of the main() function is declaring a pointer. However, that pointer is never initialized to point to some memory block that the program owns.
Suggest using one of the heap allocation functions (malloc, calloc, realloc) to initialize that pointer.
Using that uninitialized pointer is undefined behavior and (as you saw) leads to a seg fault event.
when calling any of the scanf() family of functions,
always check the returned value (not the parameter values) to assure the operation was successful.
when using the '%s' input/format specifier, always include a MAX
CHARACTERS modifier that is one less than the length of the input
buffer to avoid any buffer overflow. Such overflow is undefined
behavior and can lead to a seg fault event.
Related
I'm trying to implement a function that concatenate two strings, but I keep getting the same error.
"pointer being realloc'd was not allocated"
When I compiled the same code on a windows machine it worked, is it something that I'm missing?
The code below is basically what I'm trying to do.
main:
int main() {
int length = 4096;
char *string = malloc(length * sizeof(char));
createString(string, length);
realloc(string, 30);
return 0;
}
createString:
void createString(char * string, int length) {
char *copyAdress = string;
char *temp ="";
int counter2 = 0;
fflush(stdin);
fgets(string, length,stdin);
while(*string != EOF && *string != *temp ) {
string++;
counter++;
}
string = copyAdress;
realloc(string, (counter)*sizeof(char));
}
Thanks!
Edit:
I want createString to change the size of string to the length of the string that I get with fgets, while having the same address as the string that I sent in, so I can allocate more memory to it later when I want to add another string to it.
There are several issues:
realloc(string, (counter)*sizeof(char)); is wrong, you need string = realloc(string, (counter)*sizeof(char)); because realloc may return a different address.
Calling createString(string, length); won't modify string
If you want a more accurate answer you need to tell us what exactly createString is supposed to do. In your code there is no attempt to concatenate two strings.
Let's work through this in order of execution.
fflush(stdin); is undefined behaviour. If you really need to clear everything in the stdin you have to find another way (a loop for example). There are compilers/systems with a defined implementation but I would not count on it.
string++; is superflous as you overwrite string after the loop.
realloc(string, (counter)*sizeof(char));
should be
char *temp = realloc(string, (counter)*sizeof(char));
if (temp != NULL)
string = temp;
This way you get the pointer where your new string is located, but I suggest you read the refecerence for realloc. In essence you do not know if it has been moved and the old address might be invalid from that point on. So dereferencing it is also undefined behaviour.
After this you would have to return the new address of string or pass the address of the pointer to your function.
The same problem repeats with the second realloc. You only got to know your first call was wrong, because the second call noticed that you do not have valid data in what you thought would be your string.
In regards to your comment: It is not possible to use realloc and to be sure that the reallocated memory is in the same place as before.
If you realloc some memory, the pointer pointing to the original memory becomes invalid (unless realloc failed and returned NULL). So calling realloc twice on the same pointer should indeed not work (if it didn't return NULL the first time).
See the answers from others about what you do wrong. However, the eror message means that on MacOS, the realloc in createString deallocated the orignal string and allocated a new one, and now your realloc in main tries to realloc a pointer that is no longer valid (allocated). On Windows, the memory was not deallocated in createString and so the second call of realloc (in main) is given a valid pointer.
i am new in c programming and i just learn about pointer and string,i know when working with pointer and string we must allocate memory for string we want do declared using dynamic memory allocation.I want to calculate length of string without using c function library strlen().but why this below code doesn't give the real length of string,instead when i change *string to string[50] that means i am using array way to calculate,the code works fine and give me the real length of string.
this the code:
#include <stdio.h>
#include <stdlib.h>
int len(char *string);
int main(void){
char *string;
string=(char *)malloc(len(string+1));
puts("enter string:");
fgets(string,sizeof(string),stdin);
printf("length=%d\n",len(string));
return 0;
}
int len(char *string){
int len;
while(*string!='\0'){
string++;
len++;
}
return len-1;
}
this is when i run that code:
enter string:
programming
length=2
Your code describes the chicken and egg problem. To calculate the length, you need a pointer with allocated space & to allocate space you need to calculate the length.
In
string=(char *)malloc(len(string+1));
In malloc(), you are passing string which is a pointer which hasn't yet been initialized or allocated any memory, meaning it contains some garbage value. And then when you calculate its length in len(), it de-references the garbage address it contains, surprisingly you don't get a segfault here.
And then you have not initialized len variable in your len() function, it just adds to the garbage value that len contains and returns.
I ran your code and it gave me a segmentation fault because of the issues mentioned above.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main(){
char *s;
printf("enter the string : ");
scanf("%s", s);
printf("you entered %s\n", s);
return 0;
}
When I provide small inputs of length up to 17 characters (for example "aaaaaaaaaaaaaaaaa") the program works perfectly fine but on providing inputs of larger lengths, it gives me a runtime error saying "main.c has stopped working unexpectedly".
Is there some problem with my compiler (codeblocks) or my pc (windows 7)? Or is it somehow related to the input buffer of C?
It's undefined behaviour as the pointer is uninitialized. There's no problem with your compiler but your code has problem :)
Make s point to valid memory before storing data in there.
To manage buffer overflow, you can specify the length in the format specifier:
scanf("%255s", s); // If s holds a memory of 256 bytes
// '255' should be modified as per the memory allocated.
GNU C supports an non-standard extension with which you don't have to allocate memory as allocation is done if %as is specified but a pointer to pointer should be passed:
#include<stdio.h>
#include<stdlib.h>
int main() {
char *s,*p;
s = malloc(256);
scanf("%255s", s); // Don't read more than 255 chars
printf("%s", s);
// No need to malloc `p` here
scanf("%as", &p); // GNU C library supports this type of allocate and store.
printf("%s", p);
free(s);
free(p);
return 0;
}
the char pointer is not initialized, you should dynamiclly allocate memory to it,
char *s = malloc(sizeof(char) * N);
where N is the maximum string size you can read, And its not safe to use scanf
without specifying the maximum length for the input string, use it like this,
scanf("%Ns",s);
where N same as that for malloc.
You are not allocating any memory to the character array so first try to get memory by calling malloc() or calloc(). then try to use it.
s = malloc(sizeof(char) * YOUR_ARRAY_SIZE);
...do your work...
free(s);
You need to allocate enough memory for buffer where your pointer will point to:
s = malloc(sizeof(char) * BUF_LEN);
and then free this memory if you do not need it anymore:
free(s);
You're not allocating memory for your string, and thus, you're trying to write in a non-authorized memory address. Here
char *s;
You're just declaring a pointer. You're not specifying how much memory to reserve for your string. You can statically declare this like:
char s[100];
which will reserve 100 characters. If you go beyond 100, it will still crash as you mentionned for the same reason again.
The problem is with your code .. you never allocate memory for the char *. Since, there is no memory allocated(with malloc()) big enough to hold the string, this becomes an undefined behavior..
You must allocate memory for s and then use scanf()(I prefer fgets())
#include"stdio.h"
#include"malloc.h"
int main(){
char *str;
str=(char*)malloc(sizeof(char)*30);
printf("\nENTER THE STRING : ");
fgets(str,30,stdin);
printf("\nSTRING IS : %s",str);
return 0;
}
The code in C to read a character pointer
#include<stdio.h>
#include<stdlib.h>
void main()
{
char* str1;//a character pointer is created
str1 = (char*)malloc(sizeof(char)*100);//allocating memory to pointer
scanf("%[^\n]s",str1);//hence the memory is allocated now we can store the characters in allocated memory space
printf("%s",str1);
free(str1);//free the memory allocated to the pointer
}
I was getting this problem. I tried this code below and it worked:
char *text;
scanf("%s", *&text);
I dont know how it worked. I just felt like doing it.
My code does not work. I get run time error at the moment i accept a string. What is the problem with this code?
//this is what i have in main()
char *ele,*s[max];
int *count,temp=0;
count=&temp;
printf("Enter string to insert: ");
scanf("%s",ele);
addleft(s,ele,count);
//following is the function definition
void addleft(char *s[max],char *ele,int *count)
{
int i;
if((*count)==max)
{
printf("Queue full!\n");
return;
}
for(i=*count;i>0;i--)
strcpy(s[i],s[i-1]);
strcpy(s[0],ele);
(*count)++;
printf("String inserted at left!\n");
}
ele is an uninitialised char* and has no memory associated with it and scanf() will be attempting to write to it causing undefined behaviour, a segmentation fault is probable.
You need to either dynamically allocate memory for ele or declare a local array and prevent buffer overrun when using scanf():
char ele[1024];
if (1 == scanf("%1023s", ele))
{
/* Process 'ele'. */
}
Additionally, the function addleft() is using strcpy() on s, which is an array of char* and each of the char* in the array is unitialised. This is undefined behaviour and a probable segmentation fault. To correct, you could use strdup() if it is available otherwise malloc() and strcpy():
/* Instead of:
strcpy(s[0],ele);
use:
*/
s[0] = strdup(ele);
Note that the for loop inside the addleft() function is dangerous as the char* contained within s are not necessarily of the same length. This could easily lead to writing beyond the end of arrays. However, as the elements are addresses of dynamically allocated char* you can just swap the elements instead of copying their content.
sscanf("%s", ele) is putting the input in the memory pointed to by 'ele'. But 'ele' has never been initialized to point to anything. Something like:
char ele[128];
or
char* ele = malloc(...)
should fix it up.
You are causing a buffer overflow because the pointer ele is not pointing to any allocated memory. You are writing into memory that your program needs to run, therefore crashing it. I recommend you implement mallocinto your program like this:
char *ele;
if (!(ele = malloc(50))) //allocate 50 bytes of memory
{
//allocation failed
exit(0);
}
scanf("%s", ele); //string can hold 50 bytes now
free(ele); //free allocated space
You might want to read up on the malloc function here
An easier route would just to make ele an array instead of a pointer:
char ele[50]; //ele is an array of 50 bytes
I'm trying to write a program that reads in entries from a file into a dynamically allocated array of structures using input redirection. My program compiles fine but I'm getting a segmentation fault and I'm having trouble finding the cause.
Here's my Program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct StudentData
{
char* name;
char* major;
double gpa;
} Student;
int main()
{
Student* data = (Student*)malloc(sizeof(Student)*5);
int i;
for(i = 0; i < 5; i++)
{
// allocate memory for name and read input
data[i].name = malloc(50);
*(data+i)->name == scanf("%s", (char*)&data[i].name);
// allocate memory for major and read input
data[i].major = malloc(30);
*(data+i)->major == scanf("%s", (char*)&data[i].major);
// read input for gpa
(data+i)->gpa == scanf("%lf", &data[i].gpa);
//print array
printf("%s\n%s\n%f\n", data[i].name, data[i].major, data[i].gpa);
}
}
Any clues? If it seems obvious it's because I'm relatively new to C!
This line:
*(data+i)->name == scanf("%s", (char*)&data[i].name);
Ignoring the weird and void == for a moment, &data[i].name is wrong since you're taking an address of a pointer. data[i].name would be sufficient here, since the name field is already an address scanf can write into.
And the cast to (char*) is what probably shuts the compiler up about it - did you enter it for this purpose :-) ? Because &data[i].name has the type char**, which scanf wouldn't accept, unless you forcefully casted it to char*.
As a general advice, try to avoid scanf - it leads to very unsafe code (as you've just seen!) Instead, use fgets to read a line (from the standard input too) and then break this line into its constituents. This may initially take a bit more code to implement, but leads to much safer and more predictable code.
*(data+i)->name == scanf("%s", (char*)&data[i].name);
What are you comparing the return value of scanf for? Just remove the first part. Also, data[i].name is already a pointer, so you shouldn't take the address once again. It should just be:
scanf("%s", data[i].name); // no & because name is already a pointer
And similarly:
scanf("%s", data[i].major);
scanf("%lf", &data[i].gpa); // & here because gpa is just a double
There is some unnecessary code being used with scanf, like *(data+i)->name ==. That doesn't do anything useful (and is probably causing the segfault). If it weren't causing access errors, it would compare the return value of scanf with the pointer and then ignore the result of the comparison. (A decent compiler would have warned about this.)
After getting rid of the excess code, it will be technically okay, except there is nothing to prevent buffer overrun. That's done either by controlling the input data, or adding limits to the lengths of the strings, like with scanf("%50s", data[i].name);
&data[i].name and &data[i].major are of type char **, so you cannot safely cast it to char *.
Losing the ampersand will correct your error.
There are also other logical errors with the use of scanf(), but that's probably overwhelming - it'd be nice if you revisited this code once you entered a name of more than 50 characters.