This question already has answers here:
What is the difference between char s[] and char *s?
(14 answers)
Definitive List of Common Reasons for Segmentation Faults
(1 answer)
Closed 5 years ago.
I have the following code to split strings by tokens:
char **strToWordArray(char *str, const char *delimiter)
{
char **words;
int nwords = 1;
words = malloc(sizeof(*words) * (nwords + 1));
int w = 0;
int len = strlen(delimiter);
words[w++] = str;
while (*str)
{
if (strncmp(str, delimiter, len) == 0)
{
for (int i = 0; i < len; i++)
{
*(str++) = 0;
}
if (*str != 0) {
nwords++;
char **tmp = realloc(words, sizeof(*words) * (nwords + 1));
words = tmp;
words[w++] = str;
} else {
str--;
}
}
str++;
}
words[w] = NULL;
return words;
}
If I do this:
char str[] = "abc/def/foo/bar";
char **words=strToWordArray(str,"/");
then the program works just fine but if I do this:
char *str = "abc/def/foo/bar";
char **words=strToWordArray(str,"/");
then I get a segmentation fault.
Why is that? The program expects a char* as an argument then why does a char* argument crash the program?
Because the function contains:
*(str++) = 0;
which modifies the string that was passed to it. When you do:
char *str = "abc/def/foo/bar";
str points to a read-only string literal. See the section titled Attempting to modify a string literal in this question:
Definitive List of Common Reasons for Segmentation Faults
Related
This question already has an answer here:
String literals: pointer vs. char array
(1 answer)
Closed 2 months ago.
I am trying to reverse string using pointer (ref source). in function
string_reverse
Bus Error happened at this line when copying character from char pointer end to start char pointer :
*start = *end;
I tried LLDB in VS code. .
Can some one explain why there is bus error happened at below line?
*start = *end
Full code below:
#include <stdio.h>
#include <string.h>
void string_reverse(char* str)
{
int len = strlen(str);
char temp;
char *end = str;
char *start = str;
/* Move end pointer to the last character */
for (int j = 0; j < len-1; j++)
{
end++;
}
for(int i = 0; i< len/2;i++ )
{
temp = *start;
*start = *end;
*end = temp;
/* update pointer positions */
start++;
end--;
}
}
int main( void )
{
char *str = "test string";
printf("Original string is %s\n", str);
string_reverse(str);
printf("Reverse string is %s\n", str);
return 0;
}
Actual result: Bus Error happened at line
*start = *end;
Expected output:
Reverse string is gnirts tset
The error happens because
char * str = "...";
mean you have a pointer to a string literal. It's a constant string that you can not modify.
When you change it to
char str[] = "...";
as chux-reinstate-monica mentioned, str will be char array with the length of your string, and you can modify it without any error.
This question already has answers here:
EXC_BAD_ACCESS when using strcpy()?
(3 answers)
Why can I not modify a string literal in c?
(1 answer)
Closed 2 years ago.
Why my code returns:
Exception: EXC_BAD_ACCESS (code=2, address=0x10d637fa2)
in the first time it enters the for loops?
void unAnnoyWord(char *str) {
char *out = str, mostAnnoying = 'a';
do
{
if (*str != mostAnnoying)
{
*out = *str;
}
} while (*str++);
}
char *str = "hakuna matata";
unAnnoyWord(str);
Perhaps this is what you want:
#include <stdio.h>
void unAnnoyWord(char *str) {
char *out = str, mostAnnoying = 'a';
do {
if (*str != mostAnnoying) {
*out++ = *str;
}
} while (*str++);
}
void main() {
char str[] = "hakuna matata";
char *sstr = str;
printf("%s\n",sstr);
unAnnoyWord(str);
printf("%s\n",sstr);
}
Resulting in:
hakuna matata
hkun mtt
This question already has answers here:
What is a debugger and how can it help me diagnose problems?
(2 answers)
Closed 4 years ago.
I tried to develop a function which take a string reverse letters and return pointer to string.
char *reverseStr(char s[])
{
printf("Initial string is: %s\n", s);
int cCounter = 0;
char *result = malloc(20);
while(*s != '\0')
{
cCounter++;
s++;
}
printf("String contains %d symbols\n", cCounter);
int begin = cCounter;
for(; cCounter >= 0; cCounter--)
{
result[begin - cCounter] = *s;
s--;
}
result[13] = '\0';
return result;
}
in main function I invoke the function and tried to print the result in this way:
int main()
{
char testStr[] = "Hello world!";
char *pTestStr;
puts("----------------------------------");
puts("Input a string:");
pTestStr = reverseStr(testStr);
printf("%s\n", pTestStr);
free(pTestStr);
return 0;
}
but the result is unexpected, there is no reverse string.
What is my fault?
There are multiple mistakes in the shared code, primarily -
s++; move the pointer till '\0'. It should be brought back 1 unit to
point to actual string by putting s--. Other wise the copied one will start with '\0' that will make it empty string.
Magic numbers 20 and 13. where in malloc() 1 + length of s should be
sufficient instead or 20. For 13 just move a unit ahead and put '\0'
However, using string.h library functions() this can be super easy. But I think you are doing it for learning purpose.
Therefore, Corrected code without using string.h lib function() should look like this:
char *reverseStr(char s[])
{
printf("Initial string is: %s\n", s);
int cCounter = 0;
while(*s != '\0')
{
cCounter++;
s++;
}
s--; //move pointer back to point actual string's last charecter
printf("String contains %d symbols\n", cCounter);
char *result = (char *) malloc(sizeof(char) * ( cCounter + 1 ));
if( result == NULL ) /*Check for failure. */
{
puts( "Can't allocate memory!" );
exit( 0 );
}
char *tempResult = result;
for (int begin = 0; begin < cCounter; begin++)
{
*tempResult = *s;
s--; tempResult++;
}
*tempResult = '\0';
//result[cCounter+1] = '\0';
return result;
}
Calling from main
int main()
{
char testStr[] = "Hello world!";
char *pTestStr;
puts("----------------------------------");
puts("Input a string:");
pTestStr = reverseStr(testStr);
printf("%s\n", pTestStr);
free(pTestStr);
}
Output
----------------------------------
Input a string:
Initial string is: Hello world!
String contains 12 symbols
!dlrow olleH
As per WhozCraig suggestion just by using pointer arithmetic only -
char *reverseStr(const char s[])
{
const char *end = s;
while (*end)
++end;
char *result = malloc((end - s) + 1), *beg = result;
if (result == NULL)
{
perror("Failed to allocate string buffer");
exit(EXIT_FAILURE);
}
while (end != s)
*beg++ = *--end;
*beg = 0;
return result;
}
Your code can be simplified using a string library function found in string.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *reverseStr(char s[])
{
printf("Initial string is: %s\n", s);
int cCounter = strlen(s);
char *result = malloc(cCounter + 1);
printf("String contains %d symbols\n", cCounter);
int begin = cCounter;
for(; cCounter > 0; cCounter--)
{
result[begin - cCounter] = s[cCounter - 1];
}
result[begin] = '\0';
return result;
}
int main()
{
char testStr[] = "Hello world!";
char *pTestStr;
puts("----------------------------------");
puts("Input a string:");
pTestStr = reverseStr(testStr);
printf("%s\n", pTestStr);
free(pTestStr);
return 0;
}
Output:
----------------------------------
Input a string:
Initial string is: Hello world!
String contains 12 symbols
!dlrow olleH
This question already has answers here:
strtok segmentation fault
(8 answers)
Closed 9 years ago.
I get segmentation fault with the following code using strtok. Am I using strtok correctly?
int main()
{
dummy("90:90");
return 0;
}
int dummy(char *str)
{
char *mm, *hh;
int len = strlen(str), result;
if (len <= 0 || len > 5)
{
return 0;
}
hh = strtok(str, ":");
while(hh){
printf("%s", hh);
hh = strtok(NULL, ":");
}
return result;
}
strtok modified the content of its argument, so you can't pass a string literal. Change it to:
int main()
{
char str[] = "90:90";
dummy(str);
return 0;
}
you can not use strtok() with a constant string. And that what you did in your code.
Because the strtok() edit the string and the constant strings are a read only strings.
To fix your problem, Duplicate your string in a dynamic allocated memory (read-write memory) in this way:
int dummy(char *str)
{
char *mm, *hh;
int len = strlen(str), result;
if (len <= 0 || len > 5)
{
return 0;
}
char *buf = strdup(str); // Modif here
hh = strtok(buf, ":"); // Modif here
while(hh){
printf("%s", hh);
hh = strtok(NULL, ":");
}
free(buf); // Modif here
return result;
}
When function strtok is called with the first argument being a string which is not NULL, it changes the contents of that string, so that in the following calls (with NULL) it will be able to fetch the next token.
You, however, are passing a constant string which resides in the (read-only) code-section of your program. So during run-time, the CPU attempts to write into a read-only memory section, leading to an illegal memory access.
In short, you need to declare the string as a local array in the stack of function main:
int main()
{
char str[] = "90:90";
dummy(str);
return 0;
}
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Getting Segmentation Fault
/* Reverse a string in place
*/
#import <stdio.h>
void reverse(char * str);
int main()
{
char * string = "This is a string.";
printf("%s\n", string);
reverse(string);
printf("%s\n", string);
}
void reverse(char * str)
{
char * start = str;
char * end = str;
if(0==*str)
return;
//Find the end
for(;0 != *(++end););
end--;
do
{
*end = *end ^ *start;
*start = *end ^ *start;
*end = *end ^ *start;
}while(++start < --end);
}
I'm not sure why this seg faults. Is is because I'm initializing my char * with a constant string?
You are trying to modify a string constant. Replace:
char * string = "This is a string.";
with
char string[] = "This is a string.";
to remedy that.