String allocation seg fault - why is this happening? [duplicate] - c

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.

Related

trying copy character from pointer to string [duplicate]

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.

exception in for loop? [duplicate]

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

Error "munmap_chunk(): invalid pointer" in C program

I've written the following C function to split a string in a delimiter and return the word number "num_words":
void split_string(char *string, char **result, char *delimiter, int num_words){
long unsigned int cont_len = strlen(string);
char line[cont_len];
strcpy(line, string);
int i = 0;
char *tmp;
char *p = strtok (line, delimiter);
while ((p != NULL) & (i <= num_words)){
if (i == num_words){
*result = strdup(p);
break;
}
p = strtok (NULL, delimiter);
i = i+1;
}
free(p);
}
and in main:
char *string = "hello whole world";
char *result;
char *delimiter = " ";
int num_words = 2;
split_string(string, &result, delimiter, num_words);
In this example, split_string would make result equal to "world". However, when I try to debug with gdb, I get a munmap_chunk(): invalid pointer error originated in the free(p) code line of the split_string function.
I know that strdup allocates memory, and that's why I was trying to free the p pointer. Where should I place this free? Should I only free(result) in the main instead? I've read answers on similar stackoverflow questions, but none could solve my problem...
You don't need to free the memory after strtok.
For further reading: Do I need to free the strtok resulting string?

passing a char* as argument breaks program whereas char[] does not [duplicate]

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

Split char array in 'C' to CSV's

I need to split a char array into CSV's. Actually we can do the reverse of it using strtok() like:
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="This,a,sample,string.";
char * pch;
printf ("Splitting string \"%s\" into tokens:\n",str);
pch = strtok (str,",");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, ",");
}
return 0;
}
But in my case, there's an char array suppose char bits[1024]="abcdefghijklmn". I need to get the output as a,b,c,d,e,f,g,h,i,j,k,m,n.
Is there any function or library to do this i.e. in terms of raw meaning, for every character it has to put a comma.
Just iterate over the string until you hit the end-of-string '\0' character. Or use the length of the data in the array (which may be smaller than the array size) and use a simple for loop.
This works for a null terminated string. But it will leave a dangling comma at the end.
void tokenise(char *s, char *d)
{
while(*d++ = *s++) *d++ = ',';
}
If you know the length of the string already, you can pass that through. This will not leave a dangling comma.
void tokenise(char *s, char *d, int length)
{
int i = 0;
while((*d++ = *s++) && ((i++)<(length-1))) *d++ = ',';
}
In both examples, s is a pointer to the source string and d points to the output tokenised string. It is up to the calling code to ensure the buffer d points to is sufficiently large.
you can use this simple function from old basic :
// ............................................................. string word at
char * word_at(char *tString, int upTo, char *dilim) {
int wcount;
char *rString, *temp;
temp= (char *) malloc(sizeof(char) * (strlen(tString)+1));
strcpy(temp, tString);
rString= strtok(temp, dilim);
wcount=1;
while (rString != NULL){
if (wcount==upTo) {
return rString;
}
rString= strtok(NULL, dilim);
wcount++;
}
return tString ;
}
parameter : string , index and character delimiter
return : word : ( char *)
If you find easy to implement it, then this could help you to start
char* split_all( char arr[], char ch )
{
char *new, *ptr;
new = ptr = calloc( 1, 2*strlen( arr ) ); // FIXME : Error checks
for( ; *(arr + 1) ; new++, arr++ )
{
*new = *arr;
new++;
*new = ch;
}
*new = *arr;
return ptr;
}
You can re-use, optimize this for your requirement. Its a quick and dirty solution, feel free to fix it..

Resources