Getting seg fault when trying to decrement my environment variable in C - c

Total C noob here. I know there is something wrong with my sprintf_wrapper method because before I introduced it everything was working fine. The point of the function is to take a string buffer and a number and change the string buffers value to "WHALE=[num]". I then use this new string with putenv method.
The code results in "Segmentation fault (core dumped)", I believe it occurs after sprintf_wrapper is called.
Main Method
int main(void) {
getP0Info();
putenv("WHALE=7");
forkProcesses();
int whale = atoi(getenv("WHALE"));
char new_env[50];
sleep(1);
printf("P0: %d\n", whale);
whale = whale - 1;
sprintf_wrapper(new_env, whale);
putenv(new_env);
return 0;
}
sprintf_wrapper
void sprintf_wrapper(char* str, int num) {
char buffer[10];
str = "WHALE=";
sprintf(buffer,"%d", num);
strcat(str,buffer);
}

You're assigning a string constant to the str variable, then attempting to to append to it. Because string constants typically live in read only memory, this commonly causes a core dump.
Do this instead:
void sprintf_wrapper(char* str, int num) {
sprintf(str,"WHALE=%d", num);
}

sprintf_wrapper(new_env, whale);
You are appending to a string literal, which is read-only memory.
This generates a segmentation fault because you write into memory that is not supposed to be written into.
str = "WHALE=";
Thats a read only string literal.

Related

Printing a String ( character pointer ) using Printf directly - Weird behaviour

In the following c code the 'line 10' doesn't print anything when ln8 & lb9 are removed. It just takes the input and prints nothing. But the weird thing is on addition of those 2 lines, the code works perfectly fine i.e the input string got printed twice once by for loop and once by the printf statement in ln10. (What i am trying to do is just print the input String)
I use MinGw Compiler and ran code using cmd.enter image description here
int main()
{
char *s;
scanf("%s",s);
printf("Line 9:\t");
for(int i=0;s[i]!='\0';i++) //line 8
printf("%c",*(s+i)); //line 9
printf("\nLine 12:\t%s\n",s); //line10
return 0;
}
char *s
you declare a pointer but do not allocate for it. It's undefined. Because the undefined behavior, everything can happen. (for example, When i test your program in my PC, it raises Segmentation fault (core dumped)
You have to allocate for the pointer before scanf (do not forget to free s when you do not need to use it):
char *s = malloc(sizeof(char) * MAX_LEN); // MAX_LEN: you define its value.
Or you can use the array of character:
char s[100]; // here, the string length is up to 99;
Try initializing the s using strdup.
int main()
{
char *s = strdup("");
scanf("%s",s);
printf("\nLine 12:\t%s\n",s); //line10
return 0;
}

Using strcat inside another function: Segmentation fault (core dumped)

static void foo(unsigned char *cmd)
{
strcat(cmd, "\r\n");
printf("\r\nfoo: #%s#", cmd);
}
int main()
{
foo("test");
return 0;
}
Compiler says Segmentation fault (core dumped)
What is the actual problem here?
You have undefined behaviour. You are not allowed to modify string literals. cmd points to a string literal and strcat() attempts concatenate to it, which is the problem.
int main(void)
{
char arr[256] = "test";
foo(arr);
return 0;
}
You generally need to be careful when using strcpy() and strcat() etc in C as there's a possibility that you could overflow the buffer.
In my example, I used an array size of 256 which is more than enough for your example. But if you are concatenating something of unknown size, you need to be careful.
In C string literals (like "test") are read-only arrays of characters. As they are read-only they can't be modified. As they are arrays they have a fixed size. You both try to modify the string literal, and extend it.
You are trying to append something to the string literal test which cannot be modified. It's undefined behaviour.
You want this:
static void foo(unsigned char *cmd)
{
strcat(cmd, "\r\n");
printf("\r\nfoo: #%s#", cmd);
}
int main()
{
char test[50] = "test";
foo(test);
printf("test after calling foo: %s\n", test);
return 0;
}
Other people have explained why you cannot do this operation in place.
You have basically two options:
Either you modify the string in place (with realloc() to allow you to add your suffix ("\r\n"). But you have to be careful and use a malloc allocated data.
Otherwise, allocate a new string of the size of the input, plus the size of your suffix, and copy the input string and the prefix there, and return it. In that case, the caller will need to free() the returned string (and possibly the one passed to the function, but this would have been handled eitherway).
Edit: if you use a statically allocated buffer, you'll probably have to add an additional parameter to the function indicating the size of the buffer available.
To work with I changed the program like:
static void foo(unsigned char *cmd)
{
unsigned char local[10];
strcpy(local, cmd);
strcat(local, "\r\n");
printf("\r\nfoo: #%s#", local);
}
int main()
{
foo("test");
return 0;
}

Segfault 11 on a decimal to binary function

I have a function that converts decimal to binary and returns a char * of a binary:
void decimal2binary(int decimalNum, int size, char * charPtr){
int decimalTemp = decimalNum;
int modNum;
for(int sizeTemp = size; sizeTemp >= 0; --sizeTemp){
modNum = decimalTemp >> sizeTemp;
if(modNum & 1){
strcat(charPtr, "1");
}else{
strcat(charPtr, "0");
}
}
}
When I try to test it in main, I get the correct out put as and then "Segmentation fault 11" with gcc compiler:
In int main() :
char testArr[] = "test";
char * foo = testArr;
decimal2binary(10,7, foo);
printf("%s\n", foo);
printf("asdasds\n");
Result :
test00001010
asdasds
Segmentation Fault: 11
Any ideas?
The array you pass in has a size of 5 - "test\0".
It doesn't "work" as you are writing in an invalid memory location.
More like undefined behavior.
EDIT:
If you can't tell the size of the buffer to pass in, a suggestion might be to use realloc and grow your array. Return the pointer, but remember to free the allocated memory.
You are getting segmentation fault for attempting to write on memory addresses that are not
inside your memory segment.
Use an array of bigger size or even better use pointers and keep on realloc'ing new space
as needed.

Segmentation fault (core dumped) in C, The C Programming Language by K&R Exercise 2.5 [duplicate]

This question already has answers here:
Why do I get a segmentation fault when writing to a "char *s" initialized with a string literal, but not "char s[]"?
(19 answers)
Closed 9 years ago.
I am writing a code for squeeze(s1,s2) that deletes each character in string s1 that matches any character in string s2 and I get "Segmentation fault (core dumped)" when I try to run the program.
I believe the error comes from in how i call the function inside the main(). I am a beginner and I don't know how to call functions. Please help!
#include<stdio.h>
void squeezer(char s[], char c[]);
main()
{
squeezer("abcdefgabcdefgabcdefg", "abcd");
}
void squeezer(char s[], char c[])
{
int i,j,k,z;
for(k=0; c[k] != '\0'; k++) {
for(i=j=0;s[i] != '\0';i++) {
if (s[i] != c[k]) {
s[j++] = s[i];
}
s[j] = '\0';
}
}
for(z=0; z < j; z++)
printf("%c",s[z]);
}
You are passing string literal to your function and then trying to modify it. You can't modify a string literal. Modifying a string literal invokes undefined behavior. In such case you may get either expected or unexpected result You may get segmentation fault or program crash too.
You can change your main function as
int main(void)
{
char s1[] = "abcdefgabcdefgabcdefg";
char s2[] = "abcd";
squeezer(s1, s2);
}
Must read: comp.lang.c FAQ list ยท Question 1.32.
String literals are "constant", read-only. You cannot change them, and that is what squeezer() tries to do.
You're writing to string literals, which is undefined behaviour. If your compiler put them in read-only memory, then your program should segfault. Try making writable copies of your strings in main, like so:
int main(int argc, char** argv)
{
char s[] = "abcdefgabcdefgabcdefg";
char c[] = "abcd";
squeezer(s, c);
return 0;
}
Depending on the C compiler and operating system you are using, the string literal you pass to squeezer may be "read-only" -- i.e. immutable -- at run-time. This is the same mechanism meant to prevent modification of compiled code at run-time.
The fix is to allocte a character array large enough to hold s using malloc or declare a char s[80] in main or as a global variable and then use strcpy to copy your first string literal into s before passing it as the first argument to squeezer.
Alternatively, you could pass the allocated or declared array variable as a third argument to squeezer and copy the "squeezed" string into it. Or, if you want to make squeezer as robust as you can, allocate a result array with malloc in squeezer that is strlen(s) in size, use it to accumulate the "squeezed" letters, and then return the pointer to the allocted array from squeezer whose return type will have changed from void to char *.

Segmentation fault while using char * string but not with char string[11] [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why do I get a segmentation fault when writing to a string?
Why do I get a segmentation fault when I try to modify a string constant?
I was trying to run the following two codes and I am getting a segmentation fault with file2.c but with file1.c I am not getting any fault. Can somebody explain what is the difference between the following codes :
file1.c
#include <stdio.h>
int main()
{
int i;
char string[11] = {"HelloThere"};
string[10] = '\0';
for(i =0;i<5;i++)
{
string[i] = 'a';
}
printf("%s\n",string);
}
and :
file2.c
#include <stdio.h>
int main()
{
int i;
char * string;
string = "HelloThere";
for(i =0;i<5;i++)
{
string[i] = 'a';
}
printf("%s",string);
}
This is because the assignment
char string[11] = {"HelloThere"};
copies the string constant into a writable memory, while
char * string = "HelloThere";
leaves it in the read-only memory. While it is absolutely OK to write to the writable memory (duh!) writing to read-only memory is undefined behavior, and may trigger a crash.
Note that you do not need to specify the size of your string explicitly, unless you want to allocate more memory than is required for your string literal:
char string[] = {"HelloThere"}; // <<== The size is empty
string = "HelloThere";
then
string[i] = 'a';
is wrong - you're trying to modify a string literal, which you can't. This results in undefined behavior, so anything can happen, including crashes.
However,
char sring[11] = "HelloThere";
creates an auto array (copying the contents of the string in it beforehands) and that's writable, it's allowed to modify their elements.

Resources